【问题标题】:Correct use of HttpServletResponse response.reset() and how can I get rid of it正确使用 HttpServletResponse response.reset() 以及如何摆脱它
【发布时间】:2020-03-17 05:18:32
【问题描述】:

我有一个返回 JSON 响应的 servlet。如果我执行response.getWriter 然后执行response.reset() 然后设置标题并打印输出,一切都很好。删除 response.reset() 后,在 Jetty 服务器上运行时出现异常,尽管我在浏览器中正确显示了输出。

SEVERE: Error while closing the output stream in order to commit response.
java.lang.IllegalStateException: WRITER
    at org.eclipse.jetty.server.Response.getOutputStream(Response.java:917)
    at org.glassfish.jersey.servlet.internal.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:176)
    at org.glassfish.jersey.server.ServerRuntime$Responder$1.getOutputStream(ServerRuntime.java:667)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:200)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.flushBuffer(CommittingOutputStream.java:305)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.commit(CommittingOutputStream.java:261)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.close(CommittingOutputStream.java:276)
    at org.glassfish.jersey.message.internal.OutboundMessageContext.close(OutboundMessageContext.java:839)
    at org.glassfish.jersey.server.ContainerResponse.close(ContainerResponse.java:412)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:750)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:424)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:414)
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:311)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:291)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1140)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:403)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:386)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:334)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:860)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
    at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:51)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1629)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    at org.eclipse.jetty.server.Server.handle(Server.java:530)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626)
    at java.lang.Thread.run(Thread.java:748)

我检查了API Docs,但它根本没有帮助。

工作代码(使用 response.reset())

public Response getData (
        @Context HttpServletRequest request,
        @Context HttpServletResponse response) throws IOException, SQLException, ServletException {
    Writer out = null;
    try {
        request.setCharacterEncoding("UTF-8");
        out = response.getWriter();

        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.addHeader("content-type", "gzip");

        //Print the output in json format using out.write()
    } catch (Exception e) {
        return Response.status(400).entity("{\n\"Error Message\":\"" + StringEscapeUtils.escapeJson(e.getMessage().trim()) + "\"\n}").build();
    }
    out.flush();
    return Response.ok().entity("").build();
}

我之前也尝试过设置标题,然后执行 getWriter,但这没有帮助。请建议 response.reset 到底在做什么,有什么办法可以摆脱它。

使用 Jetty 版本 9.4.8.v20180619

【问题讨论】:

    标签: java servlets jetty


    【解决方案1】:
    java.lang.IllegalStateException: WRITER
        at org.eclipse.jetty.server.Response.getOutputStream(Response.java:917)
        at org.glassfish.jersey.servlet.internal.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:176)
    

    这告诉你 Jersey 尝试使用 HttpServletResponse.getOutputStream() 之前已经有其他东西调用了 HttpServletResponse.getWriter()。这在 Servlet 规范中是不允许的,并且会导致您看到 IllegalStateException

    您为什么要在泽西岛使用 out = response.getWriter(); 自己生成响应?泽西岛是负责生成内容的人,而不是你。

    另外,我发现您的堆栈跟踪中有 GzipFilter ...

        at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:51)
    

    自 Jetty 9.0 起已弃用,改为使用 GzipHandler

    如果您这样做,您可以从代码中删除 response.addHeader("content-type", "gzip"); 调用(无论如何您都没有正确使用)

    最后,关于“使用 Jetty 版本 9.4.8.v20180619”。升级您的 Jetty 版本。

    Jetty 9.4.8 是a vulnerable version subject to multiple CVEs,使用起来不安全。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-02
      • 1970-01-01
      • 2022-08-18
      • 2021-04-03
      • 1970-01-01
      • 1970-01-01
      • 2017-12-04
      • 2023-03-17
      相关资源
      最近更新 更多