ControllerAdvice拦截Filter抛出的异常
条评论场景还原
@ControllerAdvice在spring中用于全局的异常拦截和处理。Filter则过滤请求,多用于请求鉴权。它们之间的关系如下:
因为spring设计原因,Filter和Interceptor中抛出的异常,@ControllerAdvice则捕获不到,自然也就处理不了。
解决方案
手动注入HandlerExceptionResolver对象,调用resolveException(),自己处理异常。
1 | @Autowired |
HandlerExceptionResolver.resolveException()调用逻辑如下:
1 | HandlerExceptionResolverComposite.resolveException() |
resolver.resolveException 失效情况
这种解决方案,在一些情况下,也不能正常工作。
存储标注@ControllerAdvice对象是在ExceptionHandlerExceptionResolver.exceptionHandlerAdviceCache中的。该变量初始化逻辑如下:
1 | ExceptionHandlerExceptionResolver.afterPropertiesSet() |
也就是说,spring在创建ExceptionHandlerExceptionResolver对象时,会调用afterPropertiesSet()对exceptionHandlerAdviceCache初始化。
而上述解决方案失效的情况,则是因为exceptionHandlerAdviceCache为空,也就是说没有把标注了@ControllerAdvice的对象放入该字段中。自然也就找不到异常处理的方法。
寻找原因
在向exceptionHandlerAdviceCache中put元素后,打印了一条日志Detected @ExceptionHandler methods in xxxxx。但是在日志中搜索“Detected @ExceptionHandler methods in ”发现并没有发现该日志输出,也就是说spring启动时确实没有初始化exceptionHandlerAdviceCache。
发现这个现象后,自然想到是不是因为WebMvcConfigurationSupport的原因。在我们项目自定义了MessageConverter,是通过集成WebMvcConfigurationSupport实现的。
为了排除问题,我们注释了继承的WebMvcConfigurationSupport的对象。日志中打印了“Detected @ExceptionHandler methods in ”。然后resolver.resolveException()正常运行。
问题肯定跟WebMvcConfigurationSupport有关,在WebMvcConfigurationSupport中搜索ExceptionHandler,找到问题的根源:addDefaultHandlerExceptionResolvers()。该方法逻辑如下:
- new 一个ExceptionHandlerExceptionResolver对象
- 手动调用afterPropertiesSet()
- 将对象保存,用于后续异常处理使用
该对象是有WebMvcConfigurationSupport手动new出来的,不由spring管理,所以需要手动调用afterPropertiesSet()。而在afterPropertiesSet()中初始化exceptionHandlerAdviceCache的时候,会先从applicationContext中获取标注@ControllerAdvice的对象。但是该对象不由spring管理,applicationContext自然也为null,更加获取不到标注@ControllerAdvice的对象。所以最后exceptionHandlerAdviceCache为空。
解决方案
使用@EnableWebMvc注解。提供三种使用方式:
- 直接加该注解,相当于WebMvcConfigurationSupport的配置
- 如果要自定义配置,使用@EnableWebMvc + WebMvcConfigurer 实现
- 删除@EnableWebMvc注解,使用WebMvcConfigurationSupport or DelegatingWebMvcConfiguration。这两个类都会存在上面说的坑。
- 本文链接:https://www.ofcoder.com/2020/12/10/java/ControllerAdvice%E6%8B%A6%E6%88%AAFilter%E6%8A%9B%E5%87%BA%E7%9A%84%E5%BC%82%E5%B8%B8/
- 版权声明:Copyright © 并发笔记 - ofcoder.com. Author by far.
分享