我正在使用SpringMVC,并且我想处理其他控制器上的异常。 我的控制器通常在响应输出中写入一个json,但是当发生异常时,我无法捕获它并返回tomcat html页面。SpringMVC处理其他控制器中的错误
如何根据请求中的“accept”参数捕获全局异常并返回适当的响应?
我正在使用SpringMVC,并且我想处理其他控制器上的异常。 我的控制器通常在响应输出中写入一个json,但是当发生异常时,我无法捕获它并返回tomcat html页面。SpringMVC处理其他控制器中的错误
如何根据请求中的“accept”参数捕获全局异常并返回适当的响应?
ExceptionHandler annotation正在做你想要的hwat。
@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中找到。
更新:根据评论添加更多示例。
很好的答案! @ControllerAdvice是Spring 3.2中最好的事情之一!你也可以把多个映射放到'@ExceptionHandler({Exception1.class,Exception2.class})'。更新帖子信息可能很有趣,当然我认为。 – 2013-04-30 17:14:08
用这个解决方案可以以编程方式设置响应状态吗?我需要这些用于我的用例,并且可以在我的解决方案中看到它可能在那里。但是,感谢分享这种新方法,将派上用场。 – Matsemann 2013-04-30 17:22:15
@DeividiCavarzan完成! – matsev 2013-05-01 08:47:26
另一种方法(我使用的是)创建一个全局异常处理程序,并告诉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,在那里你可以看看的请求,并决定如何应该回复给用户。在我的情况下,我正在使用杰克逊。
查看['@ 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