java - Spring MVC,将@ExceptionHandler 迁移到 HandlerExceptionResolver 以获得 RESTful 服务

标签 java spring rest spring-mvc content-type

背景

我有一个错误消息类:

@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");
}

每当客户端在发出带有 application/json 作为 Accept header 的请求后触发 RuntimeException 时,它都会收到带有正确的响应状态代码和匹配的 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() 方法。客户端的响应具有预期的状态代码,但内容类型是 text/html 正文中包含 html,而不是 Accept< 指定的 JSON 或 XLM 内容 原始请求中的 header 。

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

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 来自 AnnotationMethodHandlerExceptionResolver source ,特别是 handleResponseBody() 方法。

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

相关文章:

java - jquery.get 和 servlet

java - 获取 com.sun.xml.wss.XWSSecurityException 的 NoClassDefFoundError

spring - 使用 Spring Data JPA 的 JpaRepository 和 CrudRepository 之间到底有什么区别?

python - 如何在 python flask Restful web 服务中使用共享队列

python - 我需要通过 FastAPI 发送文件和数据。我正在尝试发送请求但无法正常工作

java - Struts2 javabean 和 setter

java - 为什么Android Studio Proguard mapping.txt文件为空(0 KB)?

java - 尽管可见,启用为 true,但子 JComponent 不会获得焦点

java - EL 内表格 :input causes unclosed tag error

rest - 为 Meteor 配置 Restivus POST 方法