Java @ControllerAdvice 不触发
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21884737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@ControllerAdvice Not Firing
提问by user676567
I'm working on a Spring MVC/Webflow Application (version 3.2) and trying to get exception handling working where I can output a custom exception message to a logfile and error.jsp. The problem I'm having is that the Exception Handler is not getting fired. I've created the following class and annotated it "@ControllerAdvice
" and put it into the same package as my controller that is throwing the exception:
我正在开发 Spring MVC/Webflow 应用程序(3.2 版)并尝试进行异常处理,我可以将自定义异常消息输出到日志文件和 error.jsp。我遇到的问题是异常处理程序没有被触发。我创建了以下类并将其注释为“ @ControllerAdvice
”,并将其放入与抛出异常的控制器相同的包中:
@ControllerAdvice
public class MyCustomExceptionController {
@ExceptionHandler(MyCustomException.class)
public ModelAndView handleMyException(MyCustomException ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/error/error");
modelAndView.addObject("errorId", ex.getErrorId());
modelAndView.addObject("message", ex.getErrorMessage());
return modelAndView;
}
}
and added the following to the mvc-config File:
并将以下内容添加到 mvc-config 文件中:
<mvc:annotation-driven/>
And included the following in my app-config File:
并在我的 app-config 文件中包含以下内容:
<context:component-scan base-package="package containing my controllers and MyCustomExceptionController">
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>
Any ideas why this isn't working?
任何想法为什么这不起作用?
回答by Sotirios Delimanolis
The <mvc:annotation-driven/>
element implicitly registers a ExceptionHandlerExceptionResolver
bean. This class has a initExceptionHandlerAdviceCache()
method which scans beans in the context to find those whose class type is annotated with @ControllerAdvice
.
该<mvc:annotation-driven/>
元素隐式注册了一个ExceptionHandlerExceptionResolver
bean。这个类有一个initExceptionHandlerAdviceCache()
方法,它在上下文中扫描 bean 以查找那些类类型用@ControllerAdvice
.
It does this by first calling ControllerAdviceBean.findAnnotatedBeans(ApplicationContext)
. Internally, this method uses ApplicationContext#getBeanDefinitionNames()
. The javadoc of this method states
它通过首先调用ControllerAdviceBean.findAnnotatedBeans(ApplicationContext)
. 在内部,此方法使用ApplicationContext#getBeanDefinitionNames()
. 此方法的 javadoc 说明
Does not consider any hierarchy this factory may participate
不考虑该工厂可能参与的任何层次结构
To clarify what this means. When you declare a ContextLoaderListener
in your deployment descriptor, it loads what we call a root or application ApplicationContext
and makes it available in the ServletContext
. When you then declare a DispatcherServlet
, it creates its own servletApplicationContext
and uses any ApplicationContext
it finds in the ServletContext
attributes loaded by the ContextLoaderListener
as a parent to that context. The hierarchy looks like so
澄清这意味着什么。当您ContextLoaderListener
在部署描述符中声明 a时,它会加载我们称为根或应用程序的内容,ApplicationContext
并使其在ServletContext
. 然后DispatcherServlet
,当您声明 a 时,它会创建自己的servlet,ApplicationContext
并使用ApplicationContext
它在ServletContext
加载的属性中找到的任何servletContextLoaderListener
作为该上下文的父级。层次结构看起来像这样
Root ApplicationContext // loaded by the ContextLoaderListener
|
Servlet ApplicationContext // loaded by the DispatcherServlet
Every ApplicationContext
has access to beans in parent contexts, but not the other way around.
每个人ApplicationContext
都可以访问父上下文中的 bean,但反过来不行。
The method above chooses not to use the beans in parent contexts and so only has access to beans in the current ApplicationContext
(BeanFactory
really).
上面的方法选择不在父上下文中使用 bean,因此只能访问当前ApplicationContext
(BeanFactory
真的)中的 bean 。
As such, if your
因此,如果您的
<context:component-scan .../>
is declared in a root ApplicationContext
as I'll assume from the name app-config
, but the
ApplicationContext
正如我从 name 中假设的那样在根中声明app-config
,但是
<mvc:annotation-driven />
is declared in the servlet ApplicationContext
, again assuming from mvc-config
, then the ExceptionHandlerExceptionResolver
looking for @ControllerAdvice
beans will not find any. It is looking for beans in the servlet context but they aren't there, they are in the root context.
在 servlet 中声明ApplicationContext
,再次假设 from mvc-config
,那么ExceptionHandlerExceptionResolver
查找@ControllerAdvice
bean 将找不到任何 bean。它正在 servlet 上下文中寻找 bean,但它们不在那里,它们在根上下文中。
回答by Brian Beech
In case anyone else runs into a problem like this - I found an error I had.
万一其他人遇到这样的问题 - 我发现了一个错误。
I only had one RequestMapping (http://localhost:8080/myapp/verify/verify)
我只有一个 RequestMapping ( http://localhost:8080/myapp/verify/verify)
In an InterceptorController
, in the PreHandle method, I explicitly threw an exception -> throw new MyCustomException("error","error.jsp")
to test my @ControllerAdvice
Exception
handling.
在InterceptorController
, 在 PreHandle 方法中,我显式地抛出了一个异常 ->throw new MyCustomException("error","error.jsp")
来测试我的@ControllerAdvice
Exception
处理。
When I went to http://localhost:8080/myapp/I would see the interceptor controller get called, my custom exception get thrown, but the @ControllerAdvice
class with my @ExceptionHandler(MyCustomException.class)
was never called.
当我访问http://localhost:8080/myapp/ 时,我会看到拦截器控制器被调用,我的自定义异常被抛出,但@ControllerAdvice
我的类@ExceptionHandler(MyCustomException.class)
从未被调用。
I added a @RequestMapping(value="/")
and it resolved my issues. Since I was attempting to go to a URI that had no @RequestMapping
associated with it, i was getting a 'NoHandlerFoundException'
which was shorting out my Exception
from bubbling up.
我添加了一个@RequestMapping(value="/")
,它解决了我的问题。由于我试图访问一个@RequestMapping
与它无关的 URI ,我得到了一个 URI,它使'NoHandlerFoundException'
我Exception
的冒泡时间缩短了。
In short, make sure the URI you're attempting to invoke has a @RequestMapping
associated with it, or have a method in your ExceptionHandler
class to deal with the NoHandlerFoundException
.
简而言之,请确保您尝试调用的 URI@RequestMapping
与其关联,或者在您的ExceptionHandler
类中有一个方法来处理NoHandlerFoundException
.
Hope this helps.
希望这可以帮助。