2013-04-30 49 views
2

我正在使用SpringMVC,并且我想处理其他控制器上的异常。 我的控制器通常在响应输出中写入一个json,但是当发生异常时,我无法捕获它并返回tomcat html页面。SpringMVC处理其他控制器中的错误

如何根据请求中的“accept”参数捕获全局异常并返回适当的响应?

+0

查看['@ ExceptionHandler'](http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html)注释。 – 2013-04-30 15:15:01

回答

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头自定义错误类,Spring将序列化到响应正文),在本例中将响应状态设置为400 - Bad Request。请注意,最后一个示例返回ResponseEntity(并且不是注释@ResponseBody),它允许您以编程方式指定响应状态和其他响应标头。有关@ExceptionHandler的更多信息可以在reference docs或我之前写的blog post中找到。

更新:根据评论添加更多示例。

+0

很好的答案! @ControllerAdvice是Spring 3.2中最好的事情之一!你也可以把多个映射放到'@ExceptionHandler({Exception1.class,Exception2.class})'。更新帖子信息可能很有趣,当然我认为。 – 2013-04-30 17:14:08

+0

用这个解决方案可以以编程方式设置响应状态吗?我需要这些用于我的用例,并且可以在我的解决方案中看到它可能在那里。但是,感谢分享这种新方法,将派上用场。 – Matsemann 2013-04-30 17:22:15

+0

@DeividiCavarzan完成! – matsev 2013-05-01 08:47:26

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,在那里你可以看看的请求,并决定如何应该回复给用户。在我的情况下,我正在使用杰克逊。