如何使用SpringBoot处理全局异常
如何使用SpringBoot处理全局异常
使用@ControllerAdvice 和 @ExceptionHandler处理全局异常
参考:
@ControllerAdvice
@ResponseBody
@Slf4j
public class ExceptionHandler {
@ResponseStatus(HttpStatus.OK)
@org.springframework.web.bind.annotation.ExceptionHandler(value = {MissingServletRequestParameterException.class})
public ViewResult<Object> missingServletRequestParameterException(MissingServletRequestParameterException e) {
return ViewResult.state(RpcCode.OPERATION_NOT_PERMITTED_CODE, e.getMessage(), null);
}
@ResponseStatus(HttpStatus.OK)
@org.springframework.web.bind.annotation.ExceptionHandler(value = {Exception.class})
public ViewResult<Object> allException(Exception e) {
ViewResult<Object> result = buildCustomException(e);
if (result == null && e.getCause() != null) {
result = buildCustomException(e.getCause() );
}
if (result != null) {
return result;
}
// 请求传参等spring抛出的异常消息显示出来用于调试
if (e instanceof ServletException || e instanceof NestedRuntimeException) {
log.warn("", e);
return ViewResult.state(RpcCode.SYSTEM_DEFAULT_ERROR_CODE, "请求错误:" + e.getMessage(), null);
}
log.error("system error:", e);
return ViewResult.state(RpcCode.SYSTEM_DEFAULT_ERROR, null);
}
/**
* 自定义异常的统一处理,各异常的message需要是汉字形式的提示文本。
* @param e
* @return
*/
private ViewResult<Object> buildCustomException(Throwable e) {
int code = RpcCode.SYSTEM_DEFAULT_ERROR_CODE;
if (e instanceof NoAuthException) {
code = RpcCode.OPERATION_NOT_PERMITTED_CODE;
} else if (e instanceof com.chj.thor.auth.v2.exception.NoAuthException) {
code = RpcCode.OPERATION_NOT_PERMITTED_CODE;
} else if (e instanceof DuplicatedException) {
code = RpcCode.RESOURCE_DUPLICATED_CODE;
} else if (e instanceof NotFoundException) {
code = RpcCode.RESOURCE_NOTFOUND_CODE;
} else if (e instanceof OperationNotPermittedException) {
code = RpcCode.OPERATION_NOT_PERMITTED_CODE;
} else if (e instanceof ParamInvalidException) {
code = ApiRpcCode.PARAM_INVALIDATED_CODE;
} else if (e instanceof UrlUnreachableException) {
code = ApiRpcCode.URL_UNREACHABLE_CODE;
} else if (e instanceof ThirdServiceException) {
code = ApiRpcCode.THIRD_SERVICE_CODE;
} else if (e instanceof ThorException) {
code = 500001;
}
if (code != RpcCode.SYSTEM_DEFAULT_ERROR_CODE) {
return ViewResult.state(code, e.getMessage(), null);
}
return null;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@org.springframework.web.bind.annotation.ExceptionHandler({
MethodArgumentNotValidException.class,//requestBody校验
})
public ViewResult<Object> methodArgumentNotValidException(MethodArgumentNotValidException e) throws MethodArgumentNotValidException {
log.info("[前置条件校验失败]", e);
Class<?> clazz = e.getParameter().getExecutable().getDeclaringClass();
//只有Controller层的参数出现问题才进行封装处理,否则直接上抛
if (clazz.getSimpleName().endsWith("Controller")) {
FieldError fieldError = e.getBindingResult().getFieldError();
String message = "INVALID PARAMS";
if (null != fieldError) {
message += ":" + fieldError.getField();
message += ":" + fieldError.getDefaultMessage();
}
return ViewResult.state(IRpcCode.ILLEGAL_ARGUMENT_CODE, message, null);
} else {
throw e;
}
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@org.springframework.web.bind.annotation.ExceptionHandler({
ConstraintViolationException.class //requestParam校验
})
public ViewResult<Object> constraintViolationException(ConstraintViolationException e) {
log.info("[前置条件校验失败]", e);
Set<ConstraintViolation<?>> validations = e.getConstraintViolations();
StringBuilder message = new StringBuilder("INVALID PARAMS");
//当配置的是failFast模式时,循环只会执行一遍
for (ConstraintViolation<?> v : validations) {
//只有Controller service层的参数出现问题才进行封装处理,否则直接上抛
if (v.getRootBeanClass().getSimpleName().endsWith("Controller") ||
v.getRootBeanClass().getSimpleName().endsWith("ServiceImpl")) {
message.append(":");
message.append(v.getPropertyPath());
message.append(":");
message.append(v.getMessage());
} else {
throw e;
}
}
return ViewResult.state(IRpcCode.ILLEGAL_ARGUMENT_CODE, message.toString(), null);
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@org.springframework.web.bind.annotation.ExceptionHandler({
HttpMessageNotReadableException.class, //requestParam校验
HttpRequestMethodNotSupportedException.class,//method不支持
HttpMediaTypeException.class,//ContentType问题
ServletRequestBindingException.class//数据绑定问题
})
public ViewResult<Object> constraintViolationException(Exception e) {
log.info("[客户端数据格式错误]", e);
return ViewResult.state(IRpcCode.ILLEGAL_ARGUMENT_CODE, e.getMessage(), null);
}
}