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

时间:2014-12-26 23:34:11

标签: java jersey jax-rs

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

}

当您在<error-page>中使用web.xml组件时,上面的代码会产生不需要的结果。例如,如果我的Response.status设置为400且我的error-page组件定义<error-code>为400,则网络服务器会将请求重定向到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?导致HTTP错误的任何其他代码都应转到error-page。或者是否有另一种解决方案不涉及error-page但会与我想要的相同?

1 个答案:

答案 0 :(得分:3)

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

示例:

return Response.status(400)
        .entity(null)
        .type(MediaType.APPLICATION_JSON)
        .build();

甚至

return Response.status(400)
        .type(MediaType.APPLICATION_JSON)
        .build();

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

但如果你这样做:

return Response.status(400)
        .entity("An error occured.")
        .type(MediaType.APPLICATION_JSON)
        .build();

或者这个:

return Response.status(400)
        .entity("")
        .type(MediaType.APPLICATION_JSON)
        .build();

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

  

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

     

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

因此,在您的情况下,问题似乎是jerseyException.getJsonResponseObj()返回null。您应该实现null检查以避免这种情况。

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

另见: