设置多个@ControllerAdvice @ExceptionHandlers 的优先级 [英] Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers
问题描述
我有多个用 @ControllerAdvice
注释的类,每个类都有一个 @ExceptionHandler
方法.
I have multipler classes annotated with @ControllerAdvice
, each with an @ExceptionHandler
method in.
处理Exception
的目的是如果没有找到更具体的处理程序,则应该使用它.
One handles Exception
with the intention that if no more specific handler is found, this should be used.
遗憾的是,Spring MVC 似乎总是使用最通用的情况(Exception
)而不是更具体的情况(例如 IOException
).
Sadly Spring MVC appears to be always using the most generic case (Exception
) rather than more specific ones (IOException
for example).
这是人们期望 Spring MVC 的行为方式吗?我正在尝试模拟 Jersey 中的模式,它评估每个 ExceptionMapper
(等效组件)以确定它处理的声明类型与抛出的异常有多远,并且始终使用最近的祖先.
Is this how one would expect Spring MVC to behave? I'm trying to emulate a pattern from Jersey, which assesses each ExceptionMapper
(equivalent component) to determine how far the declared type that it handles is from the exception that has been thrown, and always uses the nearest ancestor.
推荐答案
这是人们期望 Spring MVC 的行为方式吗?
Is this how one would expect Spring MVC to behave?
从 Spring 4.3.7 开始,Spring MVC 的行为如下:它使用 HandlerExceptionResolver
实例来处理处理程序方法抛出的异常.
As of Spring 4.3.7, here's how Spring MVC behaves: it uses HandlerExceptionResolver
instances to handle exceptions thrown by handler methods.
默认情况下,web MVC 配置注册一个 HandlerExceptionResolver
bean,一个 HandlerExceptionResolverComposite
,其中
By default, the web MVC configuration registers a single HandlerExceptionResolver
bean, a HandlerExceptionResolverComposite
, which
委托给其他 HandlerExceptionResolvers
的列表.
delegates to a list of other
HandlerExceptionResolvers
.
那些其他解析器是
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
按该顺序注册.对于这个问题,我们只关心 ExceptionHandlerExceptionResolver
.
registered in that order. For the purpose of this question we only care about ExceptionHandlerExceptionResolver
.
一个 AbstractHandlerMethodExceptionResolver
解决异常通过 @ExceptionHandler
方法.
An
AbstractHandlerMethodExceptionResolver
that resolves exceptions through@ExceptionHandler
methods.
在上下文初始化时,Spring 会生成一个 ControllerAdviceBean
每个@ControllerAdvice
它检测到的带注释的类.ExceptionHandlerExceptionResolver
将从上下文中检索这些,并使用 AnnotationAwareOrderComparator
which
At context initialization, Spring will generate a ControllerAdviceBean
for each @ControllerAdvice
annotated class it detects. The ExceptionHandlerExceptionResolver
will retrieve these from the context, and sort them using using AnnotationAwareOrderComparator
which
是OrderComparator
的扩展,支持Spring的Ordered
接口以及 @Order
和 @Priority
注释,带有由 Ordered 实例提供的 order 值静态覆盖定义的注释值(如果有).
is an extension of
OrderComparator
that supports Spring'sOrdered
interface as well as the@Order
and@Priority
annotations, with an order value provided by an Ordered instance overriding a statically defined annotation value (if any).
然后它会注册一个 ExceptionHandlerMethodResolver
用于这些 ControllerAdviceBean
实例中的每一个(将可用的 @ExceptionHandler
方法映射到它们所指的异常类型处理).这些最终以相同的顺序添加到 LinkedHashMap
(保留迭代顺序).
It'll then register an ExceptionHandlerMethodResolver
for each of these ControllerAdviceBean
instances (mapping available @ExceptionHandler
methods to the exception types they're meant to handle). These are finally added in the same order to a LinkedHashMap
(which preserves iteration order).
当异常发生时,ExceptionHandlerExceptionResolver
会遍历这些ExceptionHandlerMethodResolver
,使用第一个可以处理异常的.
When an exception occurs, the ExceptionHandlerExceptionResolver
will iterate through these ExceptionHandlerMethodResolver
and use the first one that can handle the exception.
所以这里的重点是:如果你有一个 @ControllerAdvice
和一个 @ExceptionHandler
用于 Exception
在另一个 之前注册带有
类用于更具体的异常,例如 @ExceptionHandler
的 @ControllerAdviceIOException
,第一个将被调用.如前所述,您可以通过让 @ControllerAdvice
注释类实现 Ordered
或用 @Order
或 @Priority
并给它一个适当的值.
So the point here is: if you have a @ControllerAdvice
with an @ExceptionHandler
for Exception
that gets registered before another @ControllerAdvice
class with an @ExceptionHandler
for a more specific exception, like IOException
, that first one will get called. As mentioned earlier, you can control that registration order by having your @ControllerAdvice
annotated class implement Ordered
or annotating it with @Order
or @Priority
and giving it an appropriate value.
这篇关于设置多个@ControllerAdvice @ExceptionHandlers 的优先级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!