9

背景

我有一个错误消息类:

@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触发a时Accept,它都会收到带有正确状态代码和匹配 JSON 正文的响应:

{"error":"something went wrong"}

或者,如果Accept标头是,则接收 XML 正文application/xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<errorMessage><error>something went wrong</error></errorMessage>

问题

现在,我想通过实现一个HandlerExceptionResolver来生成这个解决方案,这样我就不必将其复制/粘贴@ExceptionHandler到每个控制器(或创建一个其他控制器可以扩展的通用“父控制器”)。

但是,AbstractHandlerExceptionResolver.doResolveException()方法返回 aModelAndView而不是我的 propriety 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()调用了这个方法。客户端的响应具有预期的状态码,但内容类型为正文中的 html,而不是原始请求中text/html的标头指定的 JSON 或 XLM 内容。Accept

(旁注,上面示例中的实际异常、响应代码和文本消息并不重要,它们只是作为简单示例。)

春季版:3.1.1.RELEASE

4

2 回答 2

4

为了让@ExceptionHandlers 使用内容协商,AnnotationMethodHandlerExceptionResolver有一个setMessageConverters()方法必须与消息转换器一起提供,例如:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
    <property name="messageConverters">
        <list>
            <ref bean="xmlConverter"/>
            <ref bean="jsonConverter"/>
        </list>
    </property>
</bean>

但是由于您使用的是自定义方法,因此您可能必须自己实现此功能。最简单的方法可能是Ctrl-C Ctrl-VAnnotationMethodHandlerExceptionResolver源头,特别是handleResponseBody()方法。

于 2012-06-04T20:14:05.287 回答
4

我花了一些时间调查此事,并写了一篇博客文章,其中我提出了该问题的解决方案。

更新:如果您使用的是 Spring 3.2,则可以利用@ControllerAdvice注释。更多细节可以在我的第二篇博文中找到。

于 2012-09-23T21:07:58.337 回答