设置多个@ControllerAdvice @ExceptionHandler的优先级 [英] Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers
问题描述
我有一个带有 @ControllerAdvice
的乘法器类,每个都有一个 @ExceptionHandler
方法。
I have multipler classes annotated with @ControllerAdvice
, each with an @ExceptionHandler
method in.
一个句柄异常
,意图是如果没有找到更多的特定处理程序,应该使用这个。
One handles Exception
with the intention that if no more specific handler is found, this should be used.
可悲的是,Spring MVC似乎总是使用最通用的情况(异常
),而不是更具体的( IOException例如,
。
Sadly Spring MVC appears to be always using the most generic case (Exception
) rather than more specific ones (IOException
for example).
这是怎么会期待Spring MVC的行为?我试图效仿泽西的模式,它评估每个 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
。
其他解析器是
-
ExceptionHandlerExceptionResolver
-
ResponseStatusExceptionResolver
-
DefaultHandlerExceptionResolver
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
/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.htmlrel =noreferrer> @ControllerAdvice
注释类它检测。 ExceptionHandlerExceptionResolver
将从上下文中检索这些内容,并使用 AnnotationAwareOrderComparator
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的已订购
界面以及@Order
和@Priority
注释,其中一个
订单值由一个订单覆盖静态
定义的注释值(如果有)。
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
实例s(映射可用 @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
for 异常
,在另一个 @ControllerAdvice
类之前注册了一个 @ExceptionHandler
为一个更具体的异常,像
IOException
,第一个将被调用。如前所述,您可以通过使您的 @ControllerAdvice
注释类实现 已订购
或使用 @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 @ExceptionHandler的优先级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!