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

查看:140
本文介绍了设置多个@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.

那些其他解析器是

  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 每个@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'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 实例中的每一个(将可用的 @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 的 @ControllerAdvice 类用于更具体的异常,例如 IOException,第一个将被调用.如前所述,您可以通过让 @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屋!

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