SpringBoot全局异常处理
在类上加个 @RestControllerAdvice
注解,在方法加上 @ExceptionHandler
注解,value
给对应的异常类就行
注意如果是 @ControllerAdvice
注解的话,返回的格式不是 json
,会被 thymeleaf
等解析跳转页面
代码例子:
/**
* Service 异常处理
*
* @author oohmygosh
* @since 2021-09-29
*/
@Slf4j
@RestControllerAdvice
public class ServiceExceptionHandler {
/**
* 是否在响应结果中展示验证错误提示信息
*/
@Value("${spring.validation.message.enable:true}")
private Boolean enableValidationMessage;
/**
* 验证异常处理 - 在 @RequestBody 上添加 @Validated 处触发
*
* @param request {@link HttpServletRequest}
* @param e {@link MethodArgumentNotValidException}
*/
@ExceptionHandler({MethodArgumentNotValidException.class})
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ApiResult<?> handleMethodArgumentNotValidException(HttpServletRequest request, MethodArgumentNotValidException e) {
return ApiResult.failed(this.convertFiledErrors(e.getBindingResult().getFieldErrors()));
}
/**
* 验证异常处理 - form参数(对象参数,没有加 @RequestBody)触发
*
* @param request {@link HttpServletRequest}
* @param e {@link BindException}
*/
@ExceptionHandler({BindException.class})
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ApiResult<?> handleBindException(HttpServletRequest request, BindException e) {
return ApiResult.failed(this.convertFiledErrors(e.getBindingResult().getFieldErrors()));
}
/**
* 验证异常处理 - @Validated加在 controller 类上,
* 且在参数列表中直接指定constraints时触发
*/
@ExceptionHandler({ConstraintViolationException.class})
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ApiResult<?> handleConstraintViolationException(HttpServletRequest request, ConstraintViolationException ex) {
return ApiResult.failed(this.convertConstraintViolations(ex));
}
/**
* 转换FieldError列表为错误提示信息
*/
private String convertFiledErrors(List<FieldError> fieldErrors) {
return Optional.ofNullable(fieldErrors)
.filter(fieldErrorsInner -> this.enableValidationMessage)
.map(fieldErrorsInner -> fieldErrorsInner.stream()
.flatMap(fieldError -> Stream.of(fieldError.getField() + " " + fieldError.getDefaultMessage()))
.collect(Collectors.joining(", ")))
.orElse(null);
}
/**
* 转换ConstraintViolationException 异常为错误提示信息
*/
private String convertConstraintViolations(ConstraintViolationException constraintViolationException) {
return Optional.ofNullable(constraintViolationException.getConstraintViolations())
.filter(constraintViolations -> this.enableValidationMessage)
.map(constraintViolations -> constraintViolations.stream().flatMap(constraintViolation -> {
String path = constraintViolation.getPropertyPath().toString();
String errorMessage = path.substring(path.lastIndexOf(".") + 1) +
" " + constraintViolation.getMessage();
return Stream.of(errorMessage);
}).collect(Collectors.joining(", "))
).orElse(null);
}
/**
* 自定义 REST 业务异常
*
* @param e 异常类型
* @param resp 响应请求
*/
@ExceptionHandler(value = Throwable.class)
public ApiResult<Object> handleBadRequest(Throwable e, HttpServletResponse resp) {
/*
* 业务逻辑异常
*/
if (e instanceof ApiException) {
IErrorCode errorCode = ((ApiException) e).getErrorCode();
if (null != errorCode) {
return ApiResult.failed(errorCode);
}
return ApiResult.failed(e.getMessage());
}
if (e instanceof AccessDeniedException) {
return ApiResult.failed(e.getMessage());
}
// 参数缺失
if (e instanceof ServletException) {
return ApiResult.failed(e.getMessage());
}
// 请求参数无法读取
if (e instanceof HttpMessageNotReadableException) {
return ApiResult.failed(e.getMessage());
}
/*
系统内部异常,打印异常栈
*/
log.error("Error: handleBadRequest StackTrace : {}", ThrowableUtils.getStackTrace(e));
if (e instanceof MethodArgumentTypeMismatchException) {
resp.setStatus(301);
return ApiResult.failed("请求参数错误");
}
if (e instanceof IllegalArgumentException) {
return ApiResult.failed(e.getMessage());
}
return ApiResult.failed("Internal Server Error");
}
}
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
Blog!
喜欢就支持一下吧