自定义一个异常类,用户抛出异常后根据组装成前台需要的格式进行返回
1.自定义异常类
package com.ztccloud.naire.exception;
import lombok.Data;
@Data
public class QuestionException extends RuntimeException {
/**
* 异常码
*/
private String errorCode;
/**
* 异常信息
*/
private String msg;
public QuestionException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
this.msg = message;
}
public QuestionException() {
}
public QuestionException(Throwable cause) {
super(cause);
}
public QuestionException(String message) {
super(message);
this.msg = message;
}
}
2.异常处理类
import com.ztccloud.naire.config.ErrorProperties;
import com.ztccloud.naire.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.List;
import java.util.Optional;
@Slf4j
@RestControllerAdvice//配置一个切面,主要用于Exception
public class QuestionExceptionHandler {
private static final String DEFAULT_CODE = "ques_500";
private static final String PARAM_NOT_VALID = "ques_501";
private static final String DEFAULT_MSG = "系统异常";
@ExceptionHandler(QuestionException.class)//异常处理器
public Result<String> datacenterExceptionHandler(QuestionException e) {
log.error("", e);
Result<String> of = Result.of();
String code = e.getErrorCode();
if (StringUtils.isEmpty(code)) {
code = DEFAULT_CODE;
}
return of.setMsg(Optional.ofNullable(ErrorProperties.p.getProperty(code))
.orElseGet(() -> ErrorProperties.p.getProperty(DEFAULT_CODE)))
.setCode(code);
}
@ExceptionHandler(Exception.class)
public Result<String> exceptionHandler(Exception e) {
log.error("system exception:", e);
Result<String> of = Result.of();
return of.setMsg(DEFAULT_MSG).setCode(DEFAULT_CODE);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<String> paramExceptionHandler(BindException e) {
List<FieldError> fieldErrors = e.getFieldErrors();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < fieldErrors.size(); i++) {
FieldError error = fieldErrors.get(i);
sb.append("[").append("参数:").append(error.getField()).append(" -> ").append(error.getDefaultMessage()).append("]");
if (i != fieldErrors.size() - 1) {
sb.append("\r\n");
}
}
Result<String> of = Result.of();
return of.setMsg(sb.toString()).setCode(PARAM_NOT_VALID);
}
}
3.用于捕获filter异常的类
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
public class ErrorController {
public static final String ERROR_PATH = "/error/throw";
public static final String ATTRIBUTE = "filter.error";
@RequestMapping(ERROR_PATH)
public void reThrow(HttpServletRequest request) throws Exception {
throw ((Exception) request.getAttribute(ATTRIBUTE));
}
}
4.接口统一响应类
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 接口统一响应类
*/
@Data
@Accessors(chain = true)
public class Result<T> {
/**
* 默认返回200, 表示成功处理;其他错误码在统一异常类返回
*/
private String code = "200";
/**
* 返回数据
*/
private T data;
/**
* 提示信息
*/
private String msg;
private Result() {
}
private Result(String msg) {
this.msg = msg;
}
private Result(T data) {
this.data = data;
}
private Result(T data, String msg) {
this.data = data;
this.msg = msg;
}
public static <T> Result<T> of() {
return new Result<T>();
}
public static <T> Result<T> of(T data) {
return new Result<>(data);
}
public static <T> Result<T> of(T data, String msg) {
return new Result<>(data, msg);
}
}
然后在项目中,抛出异常,如下在filter中抛出异常
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
String url = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());
if (patterns.contains(url)|| StringUtils.containsAny(url,new String[]{"swagger","api-docs"})) {
//在白名单中的url,放行访问
filterChain.doFilter(httpRequest, httpResponse);
return;
}
RecordUser user=(RecordUser) httpRequest.getSession().getAttribute(UserControl.SESSION_USER);
if (user != null) {
//若为登录状态 放行访问
UserControl.setUser(user);
filterChain.doFilter(httpRequest, httpResponse);
} else {
//提示用户未进行登录
try {
throw new QuestionException("ques_user_1001","User not logged in!");
} catch (Exception e) {
servletRequest.setAttribute(ErrorController.ATTRIBUTE, e);
servletRequest.getRequestDispatcher(ErrorController.ERROR_PATH).forward(servletRequest, servletResponse);
}
}
}
加载项目的时候,加载错误信息文件
@Component
public class ErrorProperties {
public static Properties p = new Properties();
private static final Logger log = LoggerFactory.getLogger(ErrorProperties.class);
@PostConstruct
public void parseErrorProperties() throws IOException {
log.info("load error.properties ...");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("error.properties");
try {
p.load(in);
} catch (IOException e) {
log.error("load error.properties failed...", e);
throw e;
}
}
}