背景
我有一个错误消息类:

@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 Controller 中,此类已作为返回值分配给@ExceptionHandler:
@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
ErrorMessage handleException(RuntimeException e) {
    return new ErrorMessage("something went wrong");
}
每当客户端发出带有RuntimeException作为application/json header 的请求后触发Accept时,客户端都会收到带有正确状态码和匹配JSON正文的响应:
{"error":"something went wrong"}
或者,如果Accept header 是application/xml,则接收XML正文:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<errorMessage><error>something went wrong</error></errorMessage>

问题
现在,我想通过实现HandlerExceptionResolver来泛化此解决方案,这样我就不必将@ExceptionHandler复制/粘贴到每个 Controller (或创建其他 Controller 可以扩展的通用“父 Controller ”)。
但是,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()方法。客户端的响应具有预期的状态码,但是内容类型为体内带有html的text/html,而不是原始请求中Accept header 指定的JSON或XLM内容。
(旁注,上面示例中的实际异常,响应代码和文本消息并不重要,它们仅用作简单示例。)
Spring 版本:3.1.1.RELEASE

最佳答案

为了使@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>

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

关于java - Spring MVC,将@ExceptionHandler迁移到HandlerExceptionResolver以获取RESTful服务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10885795/

10-12 01:49