【问题标题】:HTTPServletResponse status code is not in HTTP response headerHTTPServletResponse 状态码不在 HTTP 响应标头中
【发布时间】:2012-07-26 14:12:17
【问题描述】:

我有非常简单的 JAX-RS WS:

@Stateless
@Path("/foo")
public class FooFacadeBean {     

    @GET
    @Produces(MediaType.TEXT_HTML)
    public String performFooCall(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        response.setStatus(500);
        return "Hello";
    }
}

部署后我执行: curl -v localhost:8080/foo, 结果是:

About to connect() to localhost port 8080
Trying 127.0.0.1...
connected
Connected to localhost (127.0.0.1) port 8080
GET /foo HTTP/1.1
User-Agent: curl/7.26.0
Host: localhost:8080
Accept: */

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2 Java/Sun Microsystems Inc./1.6)
Server: GlassFish Server Open Source Edition 3.1.2
Content-Type: text/html
Transfer-Encoding: chunked
Date: Thu, 26 Jul 2012 13:52:10 GMT

Hello 

Connection to host localhost left intact
Closing connection

正如您所见,HTTP 中的状态代码根本没有改变,尽管它是手动设置的。 为什么会这样?我花了很多时间在谷歌上搜索,但没有任何结果。

返回 Response 对象之类的解决方法,如下所示:

Response.status(404).entity("Hello").build();

完美运行!

Glassfish 使用 JERSEY 作为 JAX-RS 实现。我使用 Glassfish 的嵌入式变体。

【问题讨论】:

    标签: java web-services rest servlets http-headers


    【解决方案1】:

    基本上,这不是您应该使用 Jersey 的方式。

    这是发生了什么:

    • 方法执行,您与 ServletResponse 交互并将状态码设置为 500。但由于您不写入任何数据,因此未提交响应。

    • 然后该方法返回一个字符串值。由于 Jersey 无法知道您是否与 ServletResponse 进行了交互,因此它的行为正常。

    • 返回的 String 方法意味着 200 响应代码(void 意味着 204 等)。 Jersey 尝试将响应代码设置为默认值,最终通过在响应实例上调用 setStatus(200)。由于还没有提交响应,所以这不是问题,将响应的500改为200。

    • HttpServletResponse 已提交并发送回客户端。

    我假设您想要做的是返回不同的状态代码,但仅在特殊情况下。这样做的方法是在正常情况下返回一个String,然后在异常情况下抛出一个WebApplicationException

    @GET
    @Produces(MediaType.TEXT_HTML)
    public String performFooCall() {
        if (isNormal()) {
            return "Hello";
        }
        throw new WebApplicationException(Response.status(500).entity("Hello").build());
    }
    

    或者,您可以抛出一个标准异常,并使用单独的ExceptionMapper 控制它作为响应的呈现方式。

    【讨论】:

    • 你说得对,我对这个工作流程不太熟悉。你能给我一个参考吗?另外我应该怎么做才能提交 HttpServletResponse?
    • @Steve:基本上,如果您使用 Jax-RS,则根本不要处理 HttpServletRequest 和 HttpServletResponse。有关更多信息,请参阅此处的泽西用户指南:jersey.java.net/nonav/documentation/latest/index.html
    • 感谢您的帮助,我会仔细阅读手册。顺便说一句,我忘了说,当我使用 JERSEY API 为这个案例编写客户端并获得响应状态代码时,它是 500。根据您的解释,我理解 - 这是内部框架工作流程。
    【解决方案2】:

    Jersey 构建了一个新响应,因此在您的代码中设置响应代码,稍后会被覆盖。 您必须在代码中构建一个新的响应并将您的字符串放入响应中(并为此更改您的返回值),或者您可以创建一个过滤器,稍后将在过滤器链中工作并更改响应状态。

    查看here了解更多详情

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-08
      • 2014-10-10
      • 2016-09-12
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多