首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >设置多个@ControllerAdvice @ExceptionHandler的优先级

设置多个@ControllerAdvice @ExceptionHandler的优先级
EN

Stack Overflow用户
提问于 2013-10-21 15:16:57
回答 8查看 78K关注 0票数 115

我有多个用@ControllerAdvice注释的类,每个类都有一个@ExceptionHandler方法。

一个处理Exception的意图是,如果找不到更具体的处理程序,就应该使用它。

遗憾的是,Spring似乎总是使用最通用的案例(Exception),而不是更具体的案例(例如,IOException)。

这就是人们期望Spring行为的方式吗?我正在尝试模拟泽西的模式,该模式评估每个ExceptionMapper (等效组件),以确定它处理的声明类型与抛出的异常有多远,并且总是使用最近的祖先。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2013-10-21 17:18:55

这就是人们期望Spring行为的方式吗?

从Spring4.3.7开始,以下是Spring的行为方式:它使用HandlerExceptionResolver实例来处理处理程序方法引发的异常。

默认情况下,web配置注册一个HandlerExceptionResolver bean,HandlerExceptionResolverComposite,它

委托给其他HandlerExceptionResolvers的列表。

其他的解析器是

  1. ExceptionHandlerExceptionResolver
  2. ResponseStatusExceptionResolver
  3. DefaultHandlerExceptionResolver

按该顺序登记。就这个问题而言,我们只关心ExceptionHandlerExceptionResolver

通过AbstractHandlerMethodExceptionResolver方法解析异常的@ExceptionHandler

在上下文初始化时,Spring将为它检测到的每个@ControllerAdvice注释类生成一个@ControllerAdviceExceptionHandlerExceptionResolver将从上下文中检索它们,并使用以下AnnotationAwareOrderComparator对它们进行排序:

OrderComparator的扩展,它支持Spring的Ordered接口以及@Order@Priority注释,其中order值由order实例提供,覆盖静态定义的注释值(如果有的话)。

然后为每个ControllerAdviceBean实例注册一个ControllerAdviceBean(将可用的@ExceptionHandler方法映射到它们要处理的异常类型)。最后,它们以相同的顺序添加到LinkedHashMap (保留迭代顺序)中。

当出现异常时,ExceptionHandlerExceptionResolver将遍历这些ExceptionHandlerMethodResolver,并使用能够处理异常的第一个异常。

因此,这里的要点是:如果您有一个带有@ExceptionHandler for Exception@ExceptionHandler,它在另一个@ControllerAdvice类之前注册,而另一个@ControllerAdvice类有一个更具体的异常,比如IOException,那么第一个将被调用。如前所述,您可以通过让@ControllerAdvice注释的类实现Ordered或用@Order@Priority注释它并给它适当的值来控制注册顺序。

票数 180
EN

Stack Overflow用户

发布于 2013-12-09 14:47:08

索提里奥斯·德里马诺利的回答非常有帮助,在进一步的调查中,我们发现,无论如何,在春季3.2.4,寻找@ControllerAdvice注释的代码也会检查@Order注解的存在,并对ControllerAdviceBeans列表进行排序。

没有@Order注释的所有控制器的默认顺序是Ordered#LOWEST_PRECEDENCE,这意味着如果您有一个需要最低优先级的控制器,那么所有控制器都需要一个更高的顺序。

下面是一个示例,演示如何使用两个带有ControllerAdvice和Order注释的异常处理程序类,这些类可以在发生UserProfileException或RuntimeException时提供适当的响应。

代码语言:javascript
运行
复制
class UserProfileException extends RuntimeException {
}

@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
class UserProfileExceptionHandler {
    @ExceptionHandler(UserProfileException)
    @ResponseBody
    ResponseEntity<ErrorResponse> handleUserProfileException() {
        ....
    }
}

@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
class DefaultExceptionHandler {

    @ExceptionHandler(RuntimeException)
    @ResponseBody
    ResponseEntity<ErrorResponse> handleRuntimeException() {
        ....
    }
}
  • 见ControllerAdviceBean#initOrderFromBeanType()
  • 见ControllerAdviceBean#findAnnotatedBeans()
  • 请参阅ExceptionHandlerExceptionResolver#initExceptionHandlerAdviceCache()

享受吧!

票数 112
EN

Stack Overflow用户

发布于 2013-12-16 12:09:45

可以使用@Order注释更改异常处理程序的顺序。

例如:

代码语言:javascript
运行
复制
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;

@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomExceptionHandler {

    //...

}

@Order的值可以是任意整数。

票数 25
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19498378

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档