全局异常处理
2025年2月8日大约 2 分钟
全局异常处理
相关信息
Java 后端的运行时异常如果直接抛到前端就是一些堆栈信息,有些时候会暴露很多敏感信息,比如数据库表字段结构或者一些查询语句里面的敏感数据等等,全局的异常拦截就很有必要,可以处理可预见的异常
@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class GlobalRestExceptionTranslator {
/**
* 记录请求的异常
*/
final IGlobalExceptionReporter globalExceptionReporter;
/**
* 把异常如何抛出
*/
final IGlobalPrinter globalExceptionPrinter;
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public R<?> handleError(MissingServletRequestParameterException e) {
log.warn("缺少请求参数:{}", e.getMessage());
String message = "缺少必要的请求参数: " + e.getParameterName();
return R.fail(ResultCode.VALIDATE_ERROR.getCode(), message);
}
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public R<?> handleError(MethodArgumentTypeMismatchException e) {
log.warn("请求参数格式错误:{}", e.getMessage());
String message = "请求参数格式错误: " + e.getName();
return R.fail(ResultCode.VALIDATE_ERROR.getCode(), message);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public R<?> handleError(MethodArgumentNotValidException e) {
log.warn("参数验证失败:{}", e.getMessage());
return handleError(e.getBindingResult());
}
@ExceptionHandler(BindException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public R<?> handleError(BindException e) {
log.warn("参数绑定失败:{}", e.getMessage());
return handleError(e.getBindingResult());
}
private R<?> handleError(BindingResult result) {
FieldError error = result.getFieldError();
if (Objects.nonNull(error)) {
String message = error.getField() + ":" + error.getDefaultMessage();
return R.fail(ResultCode.VALIDATE_ERROR.getCode(), message);
}
return R.fail(ResultCode.VALIDATE_ERROR);
}
@ExceptionHandler(HandlerMethodValidationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public R<?> handleError(HandlerMethodValidationException e) {
List<String> messageList = e.getAllErrors().stream()
.map(MessageSourceResolvable::getDefaultMessage)
.map(s -> "【" + s + "】")
.toList();
return R.fail(ResultCode.VALIDATE_ERROR.getCode(), "请求参数验证失败:" + CollectionUtil.join(messageList, ","));
}
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public R<?> handleError(HttpMessageNotReadableException e) {
return R.fail(ResultCode.ERROR.getCode()
, Optional.ofNullable(e.getRootCause()).map(Throwable::getMessage).orElse(e.getMessage()));
}
/**
* 最后找不到是什么异常再被这里拦截
*
* @param e 异常
* @param request 请求
* @param response 响应
*/
@ExceptionHandler(Throwable.class)
public void UnknownException(Throwable e
, HttpServletRequest request
, HttpServletResponse response) {
// 记录日志
globalExceptionReporter.recording(request, e);
// 抛出异常
globalExceptionPrinter.print(e, response);
}
}
如果还有其他可预见的异常,可以在后面继续添加
贡献者
XiJieYinMango Crisp