В этом посте описаны различные методы обработки ошибок в Spring MVC 3. Код доступен на GitHub в каталоге Spring-MVC-Error-Handling. Он основан на примерах Spring MVC с аннотациями .
Обработка исключений до весны 3
До Spring 3 исключения обрабатывались с помощью HandlerExceptionResolvers. Этот интерфейс определяет один метод:
|
1
2
3
4
5
|
ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) |
Обратите внимание, что он возвращает объект ModelAndView. Таким образом, обнаружение ошибки означало переадресацию на специальную страницу. Однако этот метод не подходит для вызовов REST Ajax в JSON (например). В этом случае мы не хотим возвращать страницу, и мы можем захотеть вернуть определенный код состояния HTTP. Решение, описанное далее, доступно.
Ради этого примера были созданы два поддельных исключения CustomizedException1 и CustomizedException2. Чтобы сопоставить настроенные исключения с представлениями, можно (и можно использовать) использовать ImpleMappingExceptionResolver :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
SimpleMappingExceptionResolver getSimpleMappingExceptionResolver() { SimpleMappingExceptionResolver result = new SimpleMappingExceptionResolver(); // Setting customized exception mappings Properties p = new Properties(); p.put(CustomizedException1.class.getName(), 'Errors/Exception1'); result.setExceptionMappings(p); // Unmapped exceptions will be directed there result.setDefaultErrorView('Errors/Default'); // Setting a default HTTP status code result.setDefaultStatusCode(HttpStatus.BAD_REQUEST.value()); return result;} |
Мы сопоставляем CustomizedException1 со страницей Ошибки / Исключение1 JSP (просмотр). Мы также устанавливаем представление ошибок по умолчанию для несопоставленного исключения, а именно CustomizedException2 в этом примере. Мы также устанавливаем код состояния HTTP по умолчанию.
Вот страница Exception1 JSP, страница по умолчанию похожа:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
<%@page contentType='text/html' pageEncoding='UTF-8'%><%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core' %><!doctype html><html lang='en'><head> <meta http-equiv='Content-Type' content='text/html;' charset=UTF-8'> <title>Welcome To Exception I !!!</title></head><body> <h1>Welcome To Exception I !!!</h1> Exception special message:< ${exception.specialMsg} <a href='<c:url value='/'/>'>Home</a></body></html> |
Мы также создаем фиктивный контроллер ошибок, чтобы помочь вызвать эти исключения:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Controllerpublic class TriggeringErrorsController { @RequestMapping(value = '/throwCustomizedException1') public ModelAndView throwCustomizedException1( HttpServletRequest request,HttpServletResponse response) throws CustomizedException1 { throw new CustomizedException1( 'Houston, we have a problem!'); } @RequestMapping(value = '/throwCustomizedException2') public ModelAndView throwCustomizedException2( HttpServletRequest request,HttpServletResponse response) throws CustomizedException2 { throw new CustomizedException2( 'Something happened on the way to heaven!'); } ...} |
До весны 3 можно было бы объявить SimpleMappingExceptionResolver как @Bean в web.xml. Однако мы будем использовать HandlerExceptionResolverComposite, который мы опишем позже.
Мы также настраиваем целевую страницу для кодов состояния HTTP в web.xml, что является другим способом решения проблем:
|
1
2
3
4
|
<error-page> <error-code>404</error-code> <location>/WEB-INF/pages/Errors/My404.jsp</location></error-page> |
Что нового с весны 3.X?
Аннотация @ResponseStatus — это новое средство для установки кода статуса Http при вызове метода. Они обрабатываются ResponseStatusExceptionResolver . Аннотация @ExceptionHandler облегчает обработку исключений в Spring. Такие аннотации обрабатываются с помощью AnnotationMethodHandlerExceptionResolver .
Далее показано, как эти аннотации можно использовать для установки кода состояния HTTP для ответа при срабатывании нашего настраиваемого исключения. Сообщение возвращается в теле ответа:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
@Controllerpublic class TriggeringErrorsController { ... @ExceptionHandler(Customized4ExceptionHandler.class) @ResponseStatus(value=HttpStatus.BAD_REQUEST) @ResponseBody public String handleCustomized4Exception( Customized4ExceptionHandler ex) { return ex.getSpecialMsg(); } @RequestMapping(value = '/throwCustomized4ExceptionHandler') public ModelAndView throwCustomized4ExceptionHandler( HttpServletRequest request,HttpServletResponse response) throws Customized4ExceptionHandler { throw new Customized4ExceptionHandler('S.O.S !!!!'); }} |
На стороне пользователя, если кто-то использует Ajax-вызов, ошибку можно получить с помощью следующего (мы используем JQuery):
|
01
02
03
04
05
06
07
08
09
10
11
|
$.ajax({ type: 'GET', url: prefix + '/throwCustomized4ExceptionHandler', async: true, success: function(result) { alert('Unexpected success !!!'); }, error: function(jqXHR, textStatus, errorThrown) { alert(jqXHR.status + ' ' + jqXHR.responseText); }}); |
Некоторым людям, использующим Ajax, нравится возвращать JSON с кодом ошибки и некоторым сообщением для обработки исключений. Я нахожу это излишним. Простой номер ошибки с сообщением делает его простым.
Поскольку мы используем несколько распознавателей, нам нужен составной распознаватель (как упоминалось ранее):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Configurationpublic class ErrorHandling { ... @Bean HandlerExceptionResolverComposite getHandlerExceptionResolverComposite() { HandlerExceptionResolverComposite result = new HandlerExceptionResolverComposite(); List<HandlerExceptionResolver> l = new ArrayList<HandlerExceptionResolver>(); l.add(new AnnotationMethodHandlerExceptionResolver()); l.add(new ResponseStatusExceptionResolver()); l.add(getSimpleMappingExceptionResolver()); l.add(new DefaultHandlerExceptionResolver()); result.setExceptionResolvers(l); return result;} |
DefaultHandlerExceptionResolver разрешает стандартные исключения Spring и переводит их в соответствующие коды состояния HTTP.
Запуск примера
После компиляции пример можно запустить с помощью mvn tomcat: run. Затем просмотрите:
HTTP: // локальный: 8585 / весна-MVC-обработки ошибок /
Главная страница будет выглядеть так:
Если щелкнуть ссылку «Исключение 1», отобразится следующая страница:
Если вы нажмете на ссылку Exception 2, появится следующая страница:
Если вы нажмете кнопку «Обработчик исключений», появится всплывающее окно:
Этих методов достаточно, чтобы покрыть обработку ошибок в Spring.
Больше Spring связанных постов здесь .
Ссылка: Spring MVC Обработка ошибок от нашего партнера JCG Джерома Версринга в блоге Technical Notes .



