@ControllerAdvice Not Firing

use*_*567 8 java spring exception-handling spring-mvc

我正在开发一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

<mvc:annotation-driven/>
Run Code Online (Sandbox Code Playgroud)

并在我的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> 
Run Code Online (Sandbox Code Playgroud)

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

Sot*_*lis 8

<mvc:annotation-driven/>元素隐式注册一个ExceptionHandlerExceptionResolverbean.此类有一个initExceptionHandlerAdviceCache()方法,它在上下文中扫描bean以查找其类类型已注释的bean @ControllerAdvice.

它通过第一次调用来实现ControllerAdviceBean.findAnnotatedBeans(ApplicationContext).在内部,此方法使用ApplicationContext#getBeanDefinitionNames().这种方法的javadoc说明

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

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

Root ApplicationContext // loaded by the ContextLoaderListener
            |
Servlet ApplicationContext // loaded by the DispatcherServlet
Run Code Online (Sandbox Code Playgroud)

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

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

因此,如果你的

<context:component-scan .../>
Run Code Online (Sandbox Code Playgroud)

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

<mvc:annotation-driven />
Run Code Online (Sandbox Code Playgroud)

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

  • 很好的解释,但仍然没有解决方案 (2认同)
  • 根据答案,解决方案很简单 - 我刚刚将mvc-config中的<mvc:annotation-driven />移动到app-config,一切都开始工作了 (2认同)