Статьи

Spring MVC Пример обработки ошибок

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