В этом посте описаны различные методы обработки ошибок в 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
|
@Controller public 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
|
@Controller public 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
|
@Configuration public 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 .