@ControllerAdvice Not Firing

时间:2014-02-19 15:18:28

标签: java spring spring-mvc exception-handling

我正在开发一个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;
    }
}

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

<mvc:annotation-driven/>

并在我的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> 

为什么这不起作用?

2 个答案:

答案 0 :(得分:8)

<mvc:annotation-driven/>元素隐式注册ExceptionHandlerExceptionResolver bean。此类具有initExceptionHandlerAdviceCache()方法,该方法扫描上下文中的bean以查找其类类型使用@ControllerAdvice注释的bean。

首先调用ControllerAdviceBean.findAnnotatedBeans(ApplicationContext)来完成此操作。在内部,此方法使用ApplicationContext#getBeanDefinitionNames()。此方法的javadoc说明

  

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

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

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

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

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

因此,如果你的

<context:component-scan .../>

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

<mvc:annotation-driven />

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

答案 1 :(得分:0)

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

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

InterceptorController中,在PreHandle方法中,我明确地抛出了异常 - &gt; throw new MyCustomException("error","error.jsp")来测试我的@ControllerAdvice Exception处理。

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

我添加了@RequestMapping(value="/"),它解决了我的问题。由于我试图转到没有@RequestMapping与之关联的URI,因此我得到了'NoHandlerFoundException',这使我的Exception漏掉了。

简而言之,请确保您尝试调用的URI与@RequestMapping关联,或者在ExceptionHandler类中使用方法来处理NoHandlerFoundException。< / p>

希望这有帮助。