我们当项目变得比较大的时候,开始不可避免添加全局异常处理。主要为了针对项目能够进行统一的管理,这里我将异常处理基本结构写出供大家参考。
1、异常处理主要针对是异常处理的捕获类和对异常处理的具体处理方式,这里我将异常中简单分为自定义异常和其他异常。
@RestControllerAdvice
public class GlobalExceptionHandler extends BaseGlobalExceptionHandler {
@ExceptionHandler(value =Exception.class)
@ResponseStatus(HttpStatus.OK)
@Override
public DefaultErrorResultVO handleOtherException( Exception e,HttpServletRequest request){
return super.handleOtherException( e,request);
}
@ExceptionHandler(value =BaseCustomException.class)
@ResponseStatus(HttpStatus.OK)
@Override
public ResponseEntity<DefaultErrorResultVO> handleCustomException(BaseCustomException e,
HttpServletRequest request){
return super.handleCustomException( e,request);
}
}
public abstract class BaseGlobalExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 处理参数封装错误时异常
*/
protected DefaultErrorResultVO handleOtherException(Exception e,
HttpServletRequest request) {
logger.error("handleOtherException uri:{} cause by", request.getRequestURI(), e);
return DefaultErrorResultVO.failure(ResultCode.INNER_INTERFACE_EXCEPTION, e, HttpStatus.OK);
}
/**
*处理自定义异常
*/
protected ResponseEntity<DefaultErrorResultVO> handleCustomException(BaseCustomException e,
HttpServletRequest request){
logger.error("handleCustomException uri:{},exception:{},caused by", request.getRequestURI(), e.getClass(), e.getMessage());
DefaultErrorResultVO failure = DefaultErrorResultVO.failure(e);
return ResponseEntity.status(HttpStatus.valueOf(failure.getStatus())).body(failure);
}
}
2、这里将异常处理的封装实体类贴出
@Data
public class DefaultErrorResultVO {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* HTTP 响应状态码
*/
private Integer status;
private String error;
/**
* 异常堆栈精简信息
*/
private String message;
/**
* 自定义的返回值编码
*/
private Integer code;
/**
* 调用接口路径
*/
private String path;
/**
* 异常的名字
*/
private String exception;
/**
* 异常错误传递的数据
*/
private Object errors;
/**
* 发生时间
*/
private String time;
public static DefaultErrorResultVO failure(ResultCode resultCode, Throwable e, HttpStatus httpStatus, Object errors) {
DefaultErrorResultVO failure = DefaultErrorResultVO.failure(resultCode, e, httpStatus);
failure.setErrors(errors);
return failure;
}
public static DefaultErrorResultVO failure(ResultCode resultCode,Throwable e,HttpStatus httpStatus){
DefaultErrorResultVO resultVO = new DefaultErrorResultVO();
resultVO.setCode(resultCode.getCode());
resultVO.setMessage(resultCode.getMessage());
resultVO.setStatus(httpStatus.value());
resultVO.setError(httpStatus.getReasonPhrase());
resultVO.setException(e.getMessage());
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
String path = request.getRequestURI();
resultVO.setPath(path);
resultVO.setTime(formatter.format(LocalDateTime.now()));
return resultVO;
}
public static DefaultErrorResultVO failure(BaseCustomException e) {
BusinessExceptionEnum exceptionEnum = BusinessExceptionEnum.getByClass(e.getClass());
if(Objects.nonNull(exceptionEnum)){
return DefaultErrorResultVO.failure(exceptionEnum.getResultCode(), e, HttpStatus.OK);
}
DefaultErrorResultVO errorResultVO = DefaultErrorResultVO.failure(e.getResultCode() == null ? ResultCode.FAIL : e.getResultCode(), e, HttpStatus.OK, e.getData());
String message = e.getMessage();
if (!StringUtils.isEmpty(message)) {
errorResultVO.setMessage(message);
}
return errorResultVO;
}
}
3、对异常自定义的方式
@Data
public class BaseCustomException extends RuntimeException {
protected String code;
protected String message;
protected ResultCode resultCode;
protected transient Object data;
public BaseCustomException(){
}
public BaseCustomException(String message) {
this();
this.message = message;
}
public BaseCustomException(String format, Object... objects) {
this();
this.message = String.format(format, objects);
}
public BaseCustomException(ResultCode resultCode,Object data){
this(resultCode);
this.data = data;
}
public BaseCustomException(ResultCode resultCode) {
this.resultCode = resultCode;
this.code = resultCode.getCode().toString();
this.message = resultCode.getMessage();
}
}
4、具体定义异常对基本异常进行统一继承,能够对自定义异常更好统一管理
public class ParamInvalidException extends BaseCustomException {
public ParamInvalidException(){
super();
}
public ParamInvalidException(Object data){
super.data = data;
}
public ParamInvalidException(ResultCode resultCode) {
super(resultCode);
}
public ParamInvalidException(ResultCode resultCode,Object data){
super(resultCode,data);
}
public ParamInvalidException(String msg) {
super(msg);
}
public ParamInvalidException(String formatMsg, Object... objects) {
super(formatMsg,objects);
}
}
5、对于异常的枚举处理类
public enum BusinessExceptionEnum {
PARAM_INVALID(ParamInvalidException.class,ResultCode.PARAM_INVALID);
private Class<? extends BaseCustomException> aClass;
private ResultCode resultCode;
BusinessExceptionEnum(Class<? extends BaseCustomException> aClass, ResultCode resultCode) {
this.aClass = aClass;
this.resultCode = resultCode;
}
public Class<? extends BaseCustomException> getaClass() {
return aClass;
}
public static BusinessExceptionEnum getByClass(Class<? extends BaseCustomException> aClass){
for (BusinessExceptionEnum businessException : BusinessExceptionEnum.values()) {
if (businessException.aClass.equals(aClass)) {
return businessException;
}
}
return null;
}
public ResultCode getResultCode() {
return resultCode;
}
}
6、对弈异常具体编码的定义
public enum ResultCode {
SUCCESS(200, "success"),
FAIL(-1, "fail"),
PARAM_INVALID(-1000, "param invalid"),
USER_UN_LOGIN(-2000, "user no login"),
SIGN_INVALID(-3000, "sign invalid"),
SYSTEM_EXCEPTION(-4000, "system error"),
INNER_INTERFACE_EXCEPTION(-5000, "inner interface exception"),;
private Integer code;
private String message;
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
ResultCode(Integer code, String message) {
this.code = code;
this.message = message;
}
public static String getMessage(Integer code) {
for (ResultCode resultCode : ResultCode.values()) {
if (resultCode.getCode().equals(code)) {
return resultCode.getMessage();
}
}
return null;
}
}