2013-04-30 4 views
2

Я использую SpringMVC, и я хочу обработать исключение на контроллере отдыха. Мой контроллер обычно пишет json в ответном ответе, но когда возникает исключение, я не могу его поймать, и возвращается страница tomcat html.Ошибка SpringMVC в контроллере останова

Как я могу улавливать глобальные исключения и возвращать соответствующий ответ на основе параметра «принять» в запросе?

+0

Просмотрите аннотацию ['@ ExceptionHandler'] (http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html) , –

ответ

14

Аннотации @ControllerAdvice - это новая аннотация, добавленная в выпуске Spring 3.2. Из reference docs:

Классы аннотированные с @ControllerAdvice могут содержать методы @ExceptionHandler, @InitBinder и @ModelAttribute и те будут применяться к @RequestMapping методы по всей иерархии контроллера, в отличие от иерархии контроллера, в которой они объявлены. @ControllerAdvice - это аннотация компонента, позволяющая автоматически распознавать классы реализации через сканирование классов.

Пример:

@ControllerAdvice 
class GlobalControllerExceptionHandler { 

    // Basic example 
    @ExceptionHandler 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ResponseBody 
    ErrorMessage handleException(FirstException ex) { 
     ErrorMessage errorMessage = createErrorMessage(ex); 
     return errorMessage; 
    } 

    // Multiple exceptions can be handled 
    @ExceptionHandler({SecondException.class, ThirdException.class}) 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ResponseBody 
    ErrorMessage handleException() { 
     ErrorMessage errorMessage = createErrorMessage(...); 
     return errorMessage; 
    } 

    // Returning a custom response entity 
    @ExceptionHandler 
    ResponseEntity<ErrorMessage> handleException(OtherException ex) { 
     ErrorMessage errorMessage = createErrorMessage(...); 
     ResponseEntity<ErrorMessage> responseEntity = new ResponseEntity<ErrorMessage>(errorMessage, HttpStatus.BAD_REQUEST); 
     return responseEntity; 
    } 
} 

В основном, это позволяет уловить определенные исключения, создает пользовательские ErrorMessage (это ваш пользовательский класс ошибок, что весна будет сериализовать к телу ответа в соответствии с заголовком Accept) и в этом примере устанавливает статус ответа на 400 - Bad Request. Обратите внимание, что в последнем примере возвращается ResponseEntity (и это не с аннотацией @ResponseBody), что позволяет программно определить статус ответа и другие заголовки ответов. Более подробную информацию о @ExceptionHandler можно найти в reference docs или в blog post, который я написал некоторое время назад.

Обновление: добавлено больше примеров, основанных на комментариях.

+0

Хороший ответ! @ControllerAdvice - одна из лучших вещей, обновленная весной 3.2! Вы также можете поместить более одного сопоставления в '@ExceptionHandler ({Exception1.class, Exception2.class})'. Возможно, интересно обновить информацию о постах, на мой взгляд, конечно. –

+0

Можно ли программно установить статус ответа с помощью этого решения? Мне это нужно для моего использования, и, как видно из моего решения, это возможно. Но спасибо за то, что поделились новым способом сделать это, пригодится. – Matsemann

+0

@DeividiCavarzan Сделано! – matsev

1

Другой подход (то, что я использую) - создать глобальный обработчик исключений и сообщить Spring, что он должен использоваться. Тогда вам не нужно дублировать свою логику или расширять тот же базовый контроллер, что и вам, когда вы должны аннотировать метод контроллера с помощью @ExceptionHandler. Вот простой пример.

public class ExceptionHandler implements HandlerExceptionResolver { 

    @Override 
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse response, Object o, Exception e) { 
     response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // Or some other error code 
     ModelAndView mav = new ModelAndView(new MappingJackson2JsonView()); 
     mav.addObject("error", "Something went wrong: \"" + e.getMessage() + "\""); 
     return mav; 
    } 
} 

И в <something>-servlet.xml назначении его в качестве разыскиваемого exceptionResolver:

<!-- Define our exceptionHandler as the resolver for our program --> 
<bean id="exceptionResolver" class="tld.something.ExceptionHandler" /> 

Тогда все исключения будут отправлены на ваш ExceptionHandler, и там вы можете посмотреть на запрос и определить, как вы должен отвечать пользователю. В моем случае я использую Джексона.

Смежные вопросы