全局异常处理的任何框架都需要解决的问题,通过 @RestControllerAdvice
可以实现对抛出的异常进行处理,并返回一个REST风格的对象到前端。
GlobalExceptionAdvice 可以用来监听所有主动和被动抛出的异常,并可以指定异常的类型。例如可以监听未知的 Exception 并记录系统日志,HttpException 是一个继承自 RuntimeException 的自定义异常,通常是开发者主动抛出,通过在此监听后返回一个 REST 风格的视图。
@RestControllerAdvice
@Slf4j
public class GlobalExceptionAdvice {
/**
* Exception异常处理
*/
@ExceptionHandler(Exception.class)
public ResponseVO<Object> handleException(Exception e) {
log.error("全局异常捕获: ", e);
return new ResponseVO<>(ResultCode.INTERNAL_SERVER_ERROR);
}
/**
* HttpException异常处理
*/
@ExceptionHandler(HttpException.class)
public ResponseVO<Object> handleHttpException(HttpException e) {
return new ResponseVO<>(e.getCode(), e.getStatusCode(), e.getMsg());
}
/**
* ServletException异常处理
*/
@ExceptionHandler(ServletException.class)
public ResponseVO<Object> handleServletException(ServletException e) {
return new ResponseVO<>(ResultCode.FAILED.getCode(), ResultCode.FAILED.getStatusCode(), e.getMessage());
}
}
public class HttpException extends RuntimeException {
private final Integer code;
private final Integer statusCode;
private final String msg;
public HttpException(ResultCode resultCode) {
this.code = resultCode.getCode();
this.statusCode = resultCode.getStatusCode();
this.msg = resultCode.getMsg();
}
}
上一节返回统一响应时使用 ResultCode 来规范格式,当然它也可以用来规范异常信息,code 码是开发者自定义的用于和前端交互使用的码,statusCode 则是 HTTP 状态码,在返回时携带不同的状态码。
@Getter
@AllArgsConstructor
public enum ResultCode {
// 成功 0~9998
SUCCESS(0, 200, "成功"),
CREATED(1, 201, "创建成功"),
UPDATED(2, 200, "更新成功"),
DELETED(3, 200, "删除成功"),
// 基础错误 9999~10099
INTERNAL_SERVER_ERROR(9999, 500, "服务器未知错误"),
FAILED(10000, 400, "失败"),
PARAMETER_ERROR(10001, 400, "参数错误"),
DUPLICATED(10010, 400, "资源已存在"),
NOT_FOUND(10011, 404, "资源不存在"),
// 权限相关 10100~10199
UN_AUTHENTICATION(10100, 401, "未授权访问"),
UN_AUTHORIZATION(10102, 401, "认证失败"),
// 文件相关 10200~10299
FILE_EXTENSION_ERROR(10200, 401, "文件后缀名不合法"),
FILE_TOO_LARGE(10201, 413, "文件大小超限"),
FILE_TOO_MANY(10202, 413, "文件数量超限");
private final Integer code;
private final Integer statusCode;
private final String msg;
}
定义异常时,只需要在父类构造函数中传入对应的 ResultCode 即可。
public class NotFoundException extends HttpException {
public NotFoundException() {
super(ResultCode.NOT_FOUND);
}
}