使用Jersey的ExceptionMapper忽略web.xml错误页面

Kyl*_*leM 10 java jax-rs jersey

@Provider
public class JerseyExceptionMapper implements ExceptionMapper<JerseyException> {


    @Override
    public Response toResponse(JerseyException jerseyException) {
        return Response.status(jerseyException.getErrorCode()).
                entity(jerseyException.getJsonResponseObj()).
                type(MediaType.APPLICATION_JSON).
                build();
    }

}
Run Code Online (Sandbox Code Playgroud)

当您在中使用<error-page>组件时,上面的代码会产生不需要的结果web.xml.例如,如果my Response.status设置为400而我的error-page组件定义<error-code>为400,则Web服务器会将请求重定向到中定义的位置web.xml.

这显然不是我想要的REST请求.我在StackOverflow上读了另一篇帖子,说明了请求被转移到的原因error-page是因为HttpServletResponse.sendError(400)设置了.该帖子说如果你设置了HttpServletResponse.setStatus(400),那error-page将被忽略.

如果这是真的,我不知道它是如何有用的,因为我没有实现Jersey代码.我看到的选项是调查Response类源代码,并可能重新实现status方法或其他Jersey代码.这里有一个简单的选择还是我缺少的东西?

从本质上讲,我的问题是:鉴于我正在使用Jersey for REST而我正在使用错误页面,我web.xml如何使用上面的代码而忽略error-page仅用于Jersey代码?导致HTTP错误的任何其他代码都应该转到error-page.或者是否有其他解决方案不涉及error-page但将与我想要的工作相同?

unw*_*ich 6

我可以重现该问题,但前提是我将 anull作为实体内容传递。

例子:

return Response.status(400)
        .entity(null)
        .type(MediaType.APPLICATION_JSON)
        .build();
Run Code Online (Sandbox Code Playgroud)

甚至

return Response.status(400)
        .type(MediaType.APPLICATION_JSON)
        .build();
Run Code Online (Sandbox Code Playgroud)

两者都将导致重定向到为 HTTP 状态代码 400 设置的错误页面,因为如果未指定消息内容,容器将使用sendError()方法。

但如果你这样做:

return Response.status(400)
        .entity("An error occured.")
        .type(MediaType.APPLICATION_JSON)
        .build();
Run Code Online (Sandbox Code Playgroud)

或这个:

return Response.status(400)
        .entity("")
        .type(MediaType.APPLICATION_JSON)
        .build();
Run Code Online (Sandbox Code Playgroud)

容器/球衣只会使用setStatus()方法,不会重定向到错误页面。如文档中所述:

此方法用于设置没有错误时的返回状态码(例如,对于 SC_OK 或 SC_MOVED_TEMPORARILY 状态码)。

如果使用该方法设置错误码,则不会触发容器的错误页面机制。如果出现错误并且调用者希望调用 Web 应用程序中定义的错误页面,则必须改用 sendError(int, java.lang.String)。

所以在你的情况下,问题似乎是jerseyException.getJsonResponseObj()return null。您应该实施空检查以避免这种情况。

Jersey 1.x有一个错误JERSEY-1557,它描述了这个问题,它在没有修复的情况下关闭,但建议使用空实体字符串作为解决方法。
Jersey 2.x 也有一个类似的错误:JERSEY-2673

也可以看看: