我有多个用@ControllerAdvice
注解的类,每个类都有一个@ExceptionHandler
方法。
处理Exception
的目的是,如果没有找到更具体的处理程序,则应该使用它。
遗憾的是,Spring MVC似乎总是使用最通用的情况(Exception
),而不是更具体的情况(例如IOException
)。
这就是Spring MVC的行为吗?我尝试模拟Jersey的模式,它评估每个ExceptionMapper
(等效组件),以确定它处理的声明类型与抛出的异常有多远,并且总是使用最近的祖先。
8条答案
按热度按时间ohfgkhjo1#
这就是人们所期望的SpringMVC的行为吗?
从Spring 4.3.7开始,Spring MVC的行为如下:它使用
HandlerExceptionResolver
示例来处理由处理程序方法抛出的异常。默认情况下,Web MVC配置注册一个
HandlerExceptionResolver
bean,即HandlerExceptionResolverComposite
,它委派给其他
HandlerExceptionResolvers
的清单。其他解析器是
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
在此问题中,我们只关心
ExceptionHandlerExceptionResolver
。透过
@ExceptionHandler
方法解析例外状况的AbstractHandlerMethodExceptionResolver
。在上下文初始化时,Spring将为它检测到的每个带
@ControllerAdvice
注解的类生成一个ControllerAdviceBean
。是
OrderComparator
的扩展,支持Spring的Ordered
接口以及@Order
和@Priority
注解,Ordered示例提供的顺序值将覆盖静态定义的注解值(如果有)。然后为每个
ControllerAdviceBean
示例注册一个ExceptionHandlerMethodResolver
(将可用的@ExceptionHandler
方法Map到它们要处理的异常类型),最后以相同的顺序添加到LinkedHashMap
(保持迭代顺序)。当异常发生时,
ExceptionHandlerExceptionResolver
将遍历这些ExceptionHandlerMethodResolver
,并使用第一个可以处理异常的ExceptionHandlerMethodResolver
。所以这里的重点是:如果您有一个
@ControllerAdvice
,它带有Exception
的@ExceptionHandler
,它在另一个@ControllerAdvice
类之前注册,这个@ControllerAdvice
类带有@ExceptionHandler
,用于更具体的异常,比如IOException
,那么第一个类将被调用。如前所述,您可以通过让您@ControllerAdvice
注解类实现Ordered
,或者用@Order
或@Priority
对其进行注解并赋予适当的值来控制注册顺序。gfttwv5a2#
Sotirios Delimanolis的回答非常有帮助,在进一步的研究中我们发现,无论如何,在3.2.4 Spring 版中,查找@ControllerAdvice注解的代码也会检查@Order注解的存在,并对ControllerAdviceBean列表进行排序。
所有不带@Order注解的控制器的默认顺序为Ordered#LOWEST_PRECEDENCE,这意味着如果您有一个控制器需要具有最低优先级,则所有控制器都需要具有较高的顺序。
下面的示例显示了如何让两个带有ControllerAdvice和Order注解的异常处理程序类在发生UserProfileException或RuntimeException时提供适当的响应。
好好享受吧!
im9ewurl3#
可以使用
@Order
注解来变更异常处理常式的顺序。例如:
@Order
的值可以是任何整数。jm2pwxwz4#
我还在文档中发现:
https://docs.spring.io/spring-framework/docs/4.3.4.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.html#getExceptionHandlerMethod-org.springframework.web.method.HandlerMethod-java.lang.Exception-
异常处理程序方法
如果您有任何异常,请使用以下方法:
查找给定异常的@ExceptionHandler方法。默认实现首先在控制器的类层次结构中搜索方法,如果未找到,它将继续搜索其他@ExceptionHandler方法(假定检测到某些@ControllerAdvice Spring托管的Bean)。参数:handlerMethod -引发异常的方法(可能为空)exception -引发的异常返回:用于处理异常的方法,或者为null
因此这意味着如果你想解决这个问题,你将需要在抛出那些异常的控制器内添加你特定的异常处理程序. ANd来定义一个且唯一的ControllerAdvice处理全局默认异常处理程序。
这简化了过程,我们不需要Order注解来处理问题。
a2mppw5e5#
在Spring博客上的“Exception Handling in Spring MVC“文章中,在标题为”全局异常处理“的一节中,有一个类似的情况,他们的场景涉及检查异常类上注册的ResponseStatus注解,如果存在,重新抛出异常,让框架来处理它们。尝试确定是否存在更合适的处理程序并重新引发。
或者,您可以参考一些其他的异常处理策略。
ql3eal8s6#
也可以使用数字值,如下所示
值越低,优先级越高。默认值为 * {@code Ordered.LOWEST_PRECEDENCE},表示优先级最低(低于任何其他 * 指定的顺序值)
xqk2d5yq7#
要处理的重要类:
具有低优先级的其他例外
fykwrbwg8#
如果你想分开你的异常处理程序(像我一样),你可以使用
@Import
来完成。第一个