2014-02-19 3 views
8

Я работаю над Spring MVC/Webflow Application (версия 3.2) и пытаюсь обработать обработку исключений, где я могу вывести собственное сообщение об исключении в файл журнала и error.jsp. Проблема, с которой я сталкиваюсь, заключается в том, что обработчик исключений не запускается. Я создал следующий класс и аннотированный его «@ControllerAdvice» и поместите его в тот же пакет, как мой контроллер, который бросает исключение:@ControllerAdvice Not Firing

@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-конфигурационный файл:

<mvc:annotation-driven/> 

И включали следующее в моем приложение-конфигурационный файл:

<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> 

Любые идеи, почему это не работает?

+0

Метод 'handleMyException()' будет вызываться только при возникновении необработанного пользовательского исключения по вашему выбору ('MyCustomException'). Этот метод ** не вызывается ** даже после того, как вызывается «MyCustomException»? [Это] (http://viralpatel.net/blogs/spring-mvc-exception-handling-controlleradvice-annotation/) - это учебник, с которым вы можете приблизиться. – Tiny

+0

Я поставил точку останова на handleMyException, и метод никогда не вызывается даже после того, как я бросаю MyCustomException. – user676567

+0

Если вы должны были аннотировать метод по вашему выбору с помощью аннотации '@ InitBinder' в этом классе, как пример, был вызван этот метод? – Tiny

ответ

8

Элемент <mvc:annotation-driven/> неявно регистрирует фасоль ExceptionHandlerExceptionResolver. Этот класс имеет метод initExceptionHandlerAdviceCache(), который сканирует компоненты в контексте, чтобы найти тех, чей тип класса аннотируется @ControllerAdvice.

Он делает это, сначала позвонив по телефону ControllerAdviceBean.findAnnotatedBeans(ApplicationContext). Внутри этого метода используется ApplicationContext#getBeanDefinitionNames(). Javadoc этого метода утверждает

Не учитывает какой-либо иерархии этот завод может участвовать

Чтобы выяснить, что это значит. При объявлении ContextLoaderListener в дескрипторе развертывания он загружает то, что мы называем корнем или приложением ApplicationContext, и делает его доступным в ServletContext. Когда вы объявляете DispatcherServlet, он создает свой собственный сервлетApplicationContext и использует любые ApplicationContext, которые он находит в атрибутах ServletContext, загружаемых ContextLoaderListener в качестве родителя в этот контекст. Иерархия выглядит так

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

Каждого ApplicationContext имеет доступ к фасоли в родительских контекстах, но не наоборот.

Вышеупомянутый метод не использует бобы в родительских контекстах и ​​поэтому имеет доступ только к beans в текущем ApplicationContext (BeanFactory действительно).

Таким образом, если ваш

<context:component-scan .../> 

объявлен в корне ApplicationContext, как я предполагаю, что от имени app-config, но

<mvc:annotation-driven /> 

объявлен в сервлет ApplicationContext, снова предполагая, от mvc-config, то ExceptionHandlerExceptionResolver ищет @ControllerAdvice beans не найдет. Он ищет компоненты в контексте сервлета, но их нет, они находятся в корневом контексте.

+0

, так что мы должны здесь делать? – gabby

+0

@gabby Вы переставляете свои элементы конфигурации, указанные выше, вместе. –

+2

Отличное объяснение, но все же решение отсутствует – shaILU

0

В случае, если кто-то еще сталкивается с проблемой, подобной этой, - я нашел ошибку, которую я имел.

У меня был только один RequestMapping (http://localhost:8080/myapp/verify/verify)

В качестве InterceptorController, в методе PreHandle, я явно бросил исключение ->throw new MyCustomException("error","error.jsp"), чтобы проверить мое обращение @ControllerAdviceException.

Когда я пошел в http://localhost:8080/myapp/ я хотел бы видеть контроллер перехватчика дозвонился, мой обычай исключение бросит, но @ControllerAdvice класса с моим @ExceptionHandler(MyCustomException.class) никогда не называли.

Я добавил @RequestMapping(value="/"), и он решил мои проблемы. Поскольку я пытался перейти к URI, у которого не было , я получал 'NoHandlerFoundException', который закрывал мой Exception от пузырящегося вверх.

Короче говоря, убедитесь, что вы пытаетесь вызвать URI имеет @RequestMapping, связанный с ним, или метод в вашем ExceptionHandler классе, чтобы иметь дело с NoHandlerFoundException.

Надеюсь, это поможет.