设置多个@ControllerAdvice @ExceptionHandler的优先级 [英] Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers

查看:5809
本文介绍了设置多个@ControllerAdvice @ExceptionHandler的优先级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 @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

其他解析器是


  1. ExceptionHandlerExceptionResolver

  2. ResponseStatusExceptionResolver

  3. DefaultHandlerExceptionResolver

  1. ExceptionHandlerExceptionResolver
  2. ResponseStatusExceptionResolver
  3. 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's Ordered 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆