Spring MVC 中的异常处理程序
我想创建一个异常处理程序,它将拦截我的项目中的所有控制器。这可能吗?看起来我必须在每个控制器中放置一个处理程序方法。感谢您的帮助。我有一个发送 Json 响应的 spring 控制器。因此,如果发生异常,我想发送一个可以从一个地方控制的错误响应。
I want to create an exception handler which will intercept all controllers in my project. Is that possible to do? Looks like I have to put a handler method in each controller. Thanks for your help. I have a spring controller that sends Json response. So if an exception happens I want to send an error response which can be controlled from one place.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
(我找到了一种在 Spring 3.1 中实现它的方法,这在本答案的第二部分中进行了描述)
请参阅章节 16.11处理异常
除了使用之外还有一些方法
@ExceptionHandler
(参见gouki 的回答)如果您没有异常的特定逻辑,而只有特定视图,那么您可以使用 SimpleMappingExceptionResolver,它至少是 HandlerExceptionResolver 的实现,您可以在其中指定异常名称模式以及引发异常时显示的视图 (jsp)。例如:
<预置><代码>dataAccessFailure ;resourceNotFound ;accessDenied ;
<属性名称=“异常映射”>
<道具>
在Spring 3.2+中,可以使用
@ControllerAdvice
注释一个类,该类中的所有@ExceptionHandler
方法都以全局方式工作。在Spring 3.1中没有
@ControllerAdvice
。但只要稍加修改,就可以拥有类似的功能。关键是理解
@ExceptionHandler
的工作方式。在Spring 3.1中有一个类ExceptionHandlerExceptionResolver
。该类实现(在其超类的帮助下)接口HandlerExceptionResolver
并负责调用@ExceptionHandler
方法。HandlerExceptionResolver 接口只有一个方法:
当请求由 Spring 3.x 控制器方法处理时,该方法(由 org.springframework.web.method.HandlerMethod 表示) >) 是
handler
参数。ExceptionHandlerExceptionResolver
使用handler
(HandlerMethod
) 获取 Controller 类并扫描它以查找使用@ExceptionHandler
注解的方法。如果此方法之一与异常 (ex
) 匹配,则调用此方法以处理异常。 (否则返回 null 以表明此异常解析器不承担任何责任)。第一个想法是实现一个自己的
HandlerExceptionResolver
,其行为类似于ExceptionHandlerExceptionResolver
,但不应在控制器类中搜索@ExceptionHandler
,而是应该在一颗特殊的豆子中寻找它们。缺点是,必须(复制(或子类 ExceptionHandlerExceptionResolver )并且必须)手动配置所有好的消息转换器、参数解析器和返回值处理程序(真正的配置并且仅< code>ExceptionHandlerExceptionResolver 由 spring 自动完成)。因此,我提出了另一个想法:实现一个简单的 HandlerExceptionResolver,将异常“转发”到(已配置的)ExceptionHandlerExceptionResolver,但使用修改后的处理程序code> 指向包含全局异常处理程序的 bean(我称它们为全局异常处理程序,因为它们为所有控制器执行工作)。
这是实现: GlobalMethodHandlerExeptionResolver
全局处理程序必须实现此接口(以便找到并实现用于处理程序的
fakeHanderMethod
>全局处理程序的示例:
顺便说一句:您不需要注册
GlobalMethodHandlerExeptionResolver
因为 spring 自动注册所有实现HandlerExceptionResolver
的异常处理程序所以一个简单的
就足够了。(I found a way to implement it in Spring 3.1, this is described in the second part of this answer)
See chapter 16.11 Handling exceptions of Spring Reference
There are some more ways than using
@ExceptionHandler
(see gouki's answer)If you do not have a specific logic for the exception, but only specifc view then you could use the SimpleMappingExceptionResolver, which is at least an implementation of the
HandlerExceptionResolver
where you can specify an Exception name pattern and the view (jsp) which is shown when the exception is thrown. For example:In Spring 3.2+ one can annotate a class with
@ControllerAdvice
, all@ExceptionHandler
methods in this class work in a global way.In Spring 3.1 there is no
@ControllerAdvice
. But with a little hack one could have a similar feature.The key is the understanding of the way
@ExceptionHandler
works. In Spring 3.1 there is a classExceptionHandlerExceptionResolver
. This class implements (with help of its superclasses) the interfaceHandlerExceptionResolver
and is responsible invoking the@ExceptionHandler
methods.The
HandlerExceptionResolver
interface has only one Method:When the request was handled by a Spring 3.x Controller Method, then this method (represented by
org.springframework.web.method.HandlerMethod
) is thehandler
parameter.The
ExceptionHandlerExceptionResolver
uses thehandler
(HandlerMethod
) to obtain the Controller class and scan it for methods annotated with@ExceptionHandler
. If one of this methods matches the exception (ex
) then this methods get invoked in order to handle the exception. (elsenull
get returned in order to signal that this exception resolver feels no responsible).The first idea would be to implement an own
HandlerExceptionResolver
that behaves likeExceptionHandlerExceptionResolver
, but instead of search for@ExceptionHandler
in the controller class, it should search for them in one special bean. The drawback would be, that one has to (copy (or subclassExceptionHandlerExceptionResolver
) and must) configure all nice message converters, argument resolvers and return value handlers by hand (the configuration of the real one and onlyExceptionHandlerExceptionResolver
is done by spring automatically). So I came up with another idea:Implement a simple
HandlerExceptionResolver
that "forwards" the exception to THE (already configured)ExceptionHandlerExceptionResolver
, BUT with an modifiedhandler
which points to the bean that contains the global Exception handlers (I call them global, because they do the work for all controllers).And this is the implementation:
GlobalMethodHandlerExeptionResolver
The global Handler has to implement this interface (in order to get found and to implement the
fakeHanderMethod
used for thehandler
And example for an global Handler:
BTW: You do not need to register the
GlobalMethodHandlerExeptionResolver
because spring automatically register all beans that implementsHandlerExceptionResolver
for exception resolvers. So a simple<bean class="GlobalMethodHandlerExeptionResolver"/>
is enough.从 Spring 3.2 开始,您可以使用 @ControllerAdvice 注释。
您可以声明 @ExceptionHandler 方法
在这种情况下,它处理来自所有控制器的@RequestMapping方法的异常。
Since Spring 3.2 you can use @ControllerAdvice annotation.
You can declare an @ExceptionHandler method within an @ControllerAdvice class
in which case it handles exceptions from @RequestMapping methods from all controllers.
您可以在其中定义异常处理程序的抽象类。然后让你的控制器继承它。
An abstract class where you define the exception handlers will do. And then make your controllers inherit it.