自定义异常类(配合结果类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* @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(运行时异常)。

定义全局异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* <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过滤器异常的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* <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())
);
}
}

}