自定义异常类(配合结果类)
/**
* @author yww
* @since 2021/10/9
**/
@Getter
@AllArgsConstructor
public class GlobalException extends RuntimeException {
/**
* 错误码
*/
private Integer code = FAILED.getCode();
/**
* 错误信息
*/
private final String message;
public GlobalException(String message) {
this.message = message;
}
public GlobalException(ResultCode resultCode) {
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
}
}
这里需要注意的是,自定义异常需要继承RuntimeException(运行时异常)。
定义全局异常处理
/**
* <p>
* 全局异常处理
* </p>
*
* @author yww
* @since 2021/10/10
**/
@Slf4j
@RestControllerAdvice
public class ControllerAdviceHandler {
/**
* 处理自定义的服务异常信息
* 统一处理GlobalException异常,异常处理顺序是从小异常到大异常。
*
* @param e 服务异常
* @return 异常信息
*/
@ExceptionHandler(value = GlobalException.class)
public <T> Result<T> globalExceptionHandler(GlobalException e, HttpServletRequest request) {
log.error(">> global exception: {}, {}, {}", request.getRequestURI(), e.getCode(), e.getMessage());
String errMessage = e.getMessage();
// 防止空的错误信息
if (StringUtils.isBlank(errMessage)) {
errMessage = "服务器繁忙";
}
return Result.failure(e.getCode(), errMessage);
}
/**
* 异常信息
*
* @param e 服务异常
* @return 异常信息
*/
@ExceptionHandler(value = Exception.class)
public <T> Result<T> defaultErrorHandler(Exception e, HttpServletRequest request) {
log.error(">> 服务器内部错误 " + request.getRequestURI(), e.getMessage());
return Result.failure(500, "服务器繁忙");
}
}
@RestControllerAdvice注解其实是@ControllerAdvice和@ResponseBody的合并。
@ControllerAdvice通常配合@ExceptionHandler来捕抓异常信息。
@ControllerAdvice可以捕抓到系统抛出的异常,然后使用@ExceptionHandler匹配具体处理异常信息。
特殊的异常处理
有些异常是不会走全局异常处理的,即不会被捕捉到,比如在过滤器中的异常,这种异常是没有经过controller的,所以发生了异常,也不会通过被上述的方式捕捉到。
以下是一个捕捉Token过滤器异常的例子。
/**
* <p>
* Token身份验证过滤器
* </p>
*
* @author yww
* @since 2022/10/20
*/
@Slf4j
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
try {
.....
// 处理Token验证的异常
} catch (AlgorithmMismatchException | SignatureVerificationException | TokenExpiredException
| MissingClaimException | IncorrectClaimException e) {
errorHandler(request, response, e);
}
}
/**
* 处理异常信息
*
* @param request 请求
* @param response 响应
* @param e 异常
*/
private void errorHandler(HttpServletRequest request, HttpServletResponse response, Exception e) {
if (e instanceof AlgorithmMismatchException) {
resolver.resolveException(request, response, null, new AlgorithmMismatchException(e.getMessage()));
return;
}
if (e instanceof TokenExpiredException) {
resolver.resolveException(request, response, null, new TokenExpiredException(
e.getMessage(),
((TokenExpiredException) e).getExpiredOn())
);
return;
}
if (e instanceof MissingClaimException) {
resolver.resolveException(request, response, null, new MissingClaimException(
((MissingClaimException) e).getClaimName())
);
return;
}
if (e instanceof IncorrectClaimException) {
resolver.resolveException(request, response, null, new IncorrectClaimException(
e.getMessage(),
((IncorrectClaimException) e).getClaimName(),
((IncorrectClaimException) e).getClaimValue())
);
return;
}
if (e instanceof JWTVerificationException) {
resolver.resolveException(request, response, null, new JWTVerificationException(
e.getMessage(),
e.getCause())
);
}
}
}