在使用统一异常处理的时候,一般使用注解的方式进行统一异常处理,具体会使用到 @ControllerAdvice
+ @ExceptionHandler
这两个注解
具体情况如下:
@ControllerAdvice
public class GlobaExceptionHandler {
//指定出现什么异常,执行这个方法
@ExceptionHandler(Exception.class)
@ResponseBody //为了能够返回数据 --- 也可以写在类的上面
public R error(Exception e){
e.printStackTrace();
return R.error().message("系统繁忙,请稍后重试!");
}
//特定异常的处理
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public R arithmeticException(ArithmeticException e){
// log.error(ExceptionUtil.getMessage(e)); //这个能够把异常的所有信息输出到文件中
e.printStackTrace();
return R.error().message("系统繁忙,请稍后重试!");
}
//特定异常的处理
@ExceptionHandler(XiaofanException.class)
@ResponseBody
public R xiaofanException(XiaofanException e){
log.error(e.getMessage()); //把自定义的异常信息输出到文件中
e.printStackTrace();
return R.error().code(e.getCode()).message(e.getMsg());
}
}
此处的R 是自定义的R类 ,把基本的返回信息都给封装进去了,或者如下方法:
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(BaseException.class)
public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {
//......
}
@ExceptionHandler(value = ResourceNotFoundException.class)
public ResponseEntity<ErrorReponse> handleResourceNotFoundException(ResourceNotFoundException ex, HttpServletRequest request) {
//......
}
}
这种异常处理方式下,会给所有或者指定的 Controller
织入异常处理的逻辑(AOP),当 Controller
中的方法抛出异常的时候,由被@ExceptionHandler
注解修饰的方法进行处理。ExceptionHandlerMethodResolver
中 getMappedMethod
方法决定了异常具体被哪个被 @ExceptionHandler
注解修饰的方法处理异常。
/*源码分析*/
@Nullable
private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
List<Class<? extends Throwable>> matches = new ArrayList<>();
//mappedMethods 中存放了异常和处理异常的方法的对应关系,找到可以处理的所有异常信息
for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
if (mappedException.isAssignableFrom(exceptionType)) {
matches.add(mappedException);
}
}
// 不为空说明有方法处理异常
if (!matches.isEmpty()) {
// 按照匹配程度从小到大排序
matches.sort(new ExceptionDepthComparator(exceptionType));
// 返回处理异常的方法
return this.mappedMethods.get(matches.get(0));
}
else {
return null;
}
}
从源代码看出: getMappedMethod()
会首先找到可以匹配处理异常的所有方法信息,然后对其进行从小到大的排序,最后取最小的那一个匹配的方法(即匹配度最高的那个)。