@ControllerAdvice Not Firing

我正在开发一个Spring MVC / Webflow应用程序(版本3.2)并试图让exception处理工作,我可以将自定义exception消息输出到日志文件和error.jsp。 我遇到的问题是exception处理程序没有被解雇。 我创建了下面的类,并将其注释为“ @ControllerAdvice ”,并将其放入与我的控制器相同的包中抛出exception:

 @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; } } 

并将以下内容添加到mvc-config文件中:

  

并在我的app-config文件中包含以下内容:

    

任何想法为什么这不起作用?

元素隐式注册ExceptionHandlerExceptionResolver bean。 此类有一个initExceptionHandlerAdviceCache()方法,该方法扫描上下文中的bean以查找其类类型使用@ControllerAdvice注释的bean。

它通过首先调用ControllerAdviceBean.findAnnotatedBeans(ApplicationContext) 。 在内部,此方法使用ApplicationContext#getBeanDefinitionNames() 。 这种方法的javadoc说明

不考虑该工厂可能参与的任何层级

澄清这意味着什么。 在部署描述符中声明ContextLoaderListener时,它会加载我们称为根或应用程序ApplicationContext并使其在ServletContext可用。 然后,当您声明DispatcherServlet ,它会创建自己的servlet ApplicationContext并使用它在ContextLoaderListener加载的ServletContext属性中找到的任何ApplicationContext作为该上下文的父级。 层次结构看起来像这样

 Root ApplicationContext // loaded by the ContextLoaderListener | Servlet ApplicationContext // loaded by the DispatcherServlet 

每个ApplicationContext都可以访问父上下文中的bean,但不能相反。

上面的方法选择不在父上下文中使用bean,因此只能访问当前ApplicationContext bean(真的是BeanFactory )。

因此,如果你的

  

我将从app-config名称中假设在根ApplicationContext声明,但是

  

在servlet ApplicationContext声明,再次假设从mvc-config ,然后查找@ControllerAdvice bean的ExceptionHandlerExceptionResolver将找不到任何。 它在servlet上下文中查找bean,但它们不存在,它们位于根上下文中。

如果其他人遇到这样的问题 – 我发现了一个错误。

我只有一个RequestMapping( http:// localhost:8080 / myapp / verify / verify )

InterceptorController ,在PreHandle方法中,我显式抛出exception – > throw new MyCustomException("error","error.jsp")来测试我的@ControllerAdvice Exception处理。

当我去http:// localhost:8080 / myapp /我会看到拦截器控制器被调用时,我的自定义exception被抛出,但是从未调用带有@ExceptionHandler(MyCustomException.class)@ControllerAdvice类。

我添加了一个@RequestMapping(value="/") ,它解决了我的问题。 由于我试图转到没有与之关联的@RequestMapping的URI,因此我得到了一个'NoHandlerFoundException' ,它将我的Exception从冒泡中缩短了。

简而言之,确保您尝试调用的URI具有与之关联的@RequestMapping ,或者在ExceptionHandler类中使用一个方法来处理NoHandlerFoundException

希望这可以帮助。