我有一个错误消息类:
@XmlRootElement
public class ErrorMessage {
private String message;
public ErrorMessage() {
}
public ErrorMessage(String message) {
this.message = message;
}
public String getError() {
return message;
}
public void setError(String message) {
this.message = message;
}
}
此类已被指定为Spring MVC REST控制器中@ExceptionHandler的返回值:
@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
ErrorMessage handleException(RuntimeException e) {
return new ErrorMessage("something went wrong");
}
每当客户端在发出RuntimeException
作为application/json
标头的请求后触发Accept
,它就会收到一个响应,其中包含正确的状态代码和匹配的JSON正文:
{"error":"something went wrong"}
或者,如果Accept
标题是application/xml
:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<errorMessage><error>something went wrong</error></errorMessage>
现在,我想通过实现HandlerExceptionResolver来生成此解决方案,这样我就不必将@ExceptionHandler
复制/粘贴到每个控制器(或者创建一个通用的“父控制器”,其他控制器可以扩展)。
但是,AbstractHandlerExceptionResolver.doResolveException()方法会返回ModelAndView
而不是我的正当ErrorMessage
,所以我尝试了以下内容:
public class RuntimeExceptionHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (ex instanceof RuntimeException) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
ModelAndView mav = new ModelAndView();
mav.addObject("error", "something went wrong");
return mav;
}
return null;
}
}
调试时,我可以看到调用mav.addObject()
方法。客户端上的响应具有预期的状态代码,但内容类型为text/html
,主体中包含html,而不是原始请求中Accept
标头指定的JSON或XLM内容。
(旁注,上面示例中的实际异常,响应代码和文本消息并不重要,它们仅作为简单示例。)
Spring版本:3.1.1.RELEASE
答案 0 :(得分:4)
要让@ExceptionHandler
使用内容协商,AnnotationMethodHandlerExceptionResolver
有一个setMessageConverters()
方法,必须与消息转换器一起提供,例如:
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
<property name="messageConverters">
<list>
<ref bean="xmlConverter"/>
<ref bean="jsonConverter"/>
</list>
</property>
</bean>
但是由于您使用的是自定义方法,因此您可能必须自己实现此功能。最简单的方法可能来自AnnotationMethodHandlerExceptionResolver
source的Ctrl-C Ctrl-V
,特别是handleResponseBody()
方法。
答案 1 :(得分:4)
我花了一些时间调查此事,我写了blog post,其中我提出了解决问题的方法。
更新:如果您使用的是Spring 3.2,则可以利用@ControllerAdvice注释。有关详细信息,请参阅我的second blog post。