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

一个人处理Exception的目的是,如果找不到更多特定的处理程序,则应使用它。

不幸的是,Spring MVC似乎总是使用最通用的情况(Exception),而不是更具体的情况(例如IOException)。

这是人们期望Spring MVC表现的方式吗?我正在尝试从Jersey模拟一个模式,该模式评估每个ExceptionMapper(等效组件)以确定它处理的声明类型与引发的异常之间的距离,并且始终使用最接近的祖先。

最佳答案



从Spring 4.3.7开始,Spring MVC的行为如下:它使用 HandlerExceptionResolver 实例来处理由处理程序方法引发的异常。

默认情况下,Web MVC配置会注册一个HandlerExceptionResolver bean HandlerExceptionResolverComposite



那些其他解析器是

  • ExceptionHandlerExceptionResolver
  • ResponseStatusExceptionResolver
  • DefaultHandlerExceptionResolver

  • 以该顺序注册。出于这个问题的目的,我们只关心 ExceptionHandlerExceptionResolver



    在上下文初始化时,Spring将为它检测到的每个带有 ControllerAdviceBean 的带注释的类生成一个 @ControllerAdvice ExceptionHandlerExceptionResolver将从上下文中检索这些内容,并使用 AnnotationAwareOrderComparator 对它们进行排序,



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

    发生异常时,ExceptionHandlerExceptionResolver将遍历这些ExceptionHandlerMethodResolver并使用可以处理该异常的第一个。

    因此,这里的要点是:如果您有一个@ControllerAdvice@ExceptionHandlerException在另一个带有@ControllerAdvice@ExceptionHandler类之前注册了更具体的异常,例如IOException,则第一个将被调用。如前所述,可以通过让带有@ControllerAdvice的注释类实现 Ordered 或使用 @Order @Priority 对其进行注释并为其指定适当的值,来控制该注册顺序。

    08-07 01:56