设置多个@ControllerAdvice @ExceptionHandlers的优先级
问题内容:
我有多个用注释的类@ControllerAdvice
,每个类都有一个@ExceptionHandler
方法。
一个处理程序Exception
的意图是,如果找不到更多特定的处理程序,则应使用该处理程序。
遗憾的是,Spring MVC似乎总是使用最通用的情况(Exception
),而不是使用更具体的情况(IOException
例如)。
这是人们期望Spring
MVC表现的方式吗?我试图从Jersey模拟一个模式,该模式评估每个ExceptionMapper
(等效组件)以确定它处理的声明类型与引发的异常之间的距离,并且始终使用最接近的祖先。
问题答案:
这是人们期望Spring MVC表现的方式吗?
从Spring 4.3.7开始,Spring
MVC的行为如下:它使用HandlerExceptionResolver
实例来处理由处理程序方法引发的异常。
默认情况下,Web MVC配置注册一个HandlerExceptionResolver
bean
HandlerExceptionResolverComposite
,即
委托其他名单
HandlerExceptionResolvers
。
那些其他解析器是
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
以该顺序注册。出于这个问题的目的,我们只关心ExceptionHandlerExceptionResolver
。
一
AbstractHandlerMethodExceptionResolver
,通过解析异常@ExceptionHandler
的方法。
在上下文初始化时,Spring将为它检测到的ControllerAdviceBean
每个带@ControllerAdvice
注释的类生成一个。该ExceptionHandlerExceptionResolver
会从上下文检索这些,并使用排序,使用AnnotationAwareOrderComparator
其
是对扩展的
OrderComparator
支持,它支持Spring的Ordered
接口以及@Order
和@Priority
批注,并由Ordered实例提供的订单值覆盖静态定义的批注值(如果有)。
然后,ExceptionHandlerMethodResolver
将为每个这些ControllerAdviceBean
实例注册一个(将可用@ExceptionHandler
方法映射到它们打算处理的异常类型)。最后,将它们以相同的顺序添加到中LinkedHashMap
(保留迭代顺序)。
当发生异常时,ExceptionHandlerExceptionResolver
会遍历这些异常ExceptionHandlerMethodResolver
并使用可以处理异常的第一个异常。
因此,这里的一点是:如果你有一个@ControllerAdvice
带有@ExceptionHandler
用于Exception
该被另一注册前@ControllerAdvice
与类@ExceptionHandler
的更具体的例外,比如IOException
,是第一个将被调用。如前所述,您可以通过@ControllerAdvice
实现Ordered
带注释的类或用@Order
或对其进行注释@Priority
并为其指定适当的值来控制该注册顺序。