Spring Boot 统一异常处理

本文将介绍如何在 SpringBoot 中进行统一异常处理。

一、@ExceptionHandler

@ExceptionHandler 能够用于定义异常的处理方法,如下:

1
2
3
4
@ExceptionHandler(异常类.class)
public ··· exception(异常类 e) {
···
}
  • 通过注解属性值指定异常类
  • 当对应的异常类发生时,将会被该方法拦截并处理

二、应用范围

@ExceptionHandler 可以在普通 Controller 类中使用,它将拦截该类中所有的对应异常;

@ExceptionHandler 也可以应用在 @ControllerAdvice 注解的接口增强类中,借助接口增强类,它能够实现全局的异常拦截。

三、@ExceptionHandler 的顺序问题

你可能有这样的疑问:@ExceptionHandler 的顺序是否影响异常的匹配?

答案是不会,@ExceptionHandler 的处理顺序是按异常的匹配程度来的。

查看源码可以发现,指定 @ExceptionHandler 的代码位于 ExceptionHandlerMethodResolver 的 getMappedMethod() 方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
List<Class<? extends Throwable>> matches = new ArrayList<Class<? extends Throwable>>();
for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
if (mappedException.isAssignableFrom(exceptionType)) {
matches.add(mappedException);
}
}
if (!matches.isEmpty()) {
Collections.sort(matches, new ExceptionDepthComparator(exceptionType));
return this.mappedMethods.get(matches.get(0));
}
else {
return null;
}
}
  • 找出所有可以匹配的 @ExceptionHandler,放入集合中
  • 调用 ExceptionDepthComparator,获取匹配深度,根据匹配深度进行排序
  • 选择排序最靠前的一个 @ExceptionHandler 进行处理

ExceptionHandler的执行顺序 - 掘金

四、示例 - 全局异常处理类

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestControllerAdvice
public class ExceptionAdvice {

/**
* 通用异常处理
*/
@ExceptionHandler(Exception.class)
public ResultVO exception(Exception e) {
e.printStackTrace();
return ResultVO.fail();
}

}

参考