应该在HttpServletResponse.getOutputStream()/.getWriter()上调用.close()吗?

Ste*_*wig 90 java servlets outputstream

我用谷歌搜索找不到权威的答案.在Java servlet中,可以通过response.getOutputStream()或response.getWriter()访问响应主体.应该在写入之后在此流上调用.close()吗?

一方面,Blochian劝告总是关闭输出流.另一方面,我认为在这种情况下不存在需要关闭的底层资源.套接字的打开/关闭在HTTP级别进行管理,以允许诸如持久连接之类的事情.

Nem*_*emi 88

通常你不应该关闭流.作为servlet请求生命周期的一部分,servlet完成运行后,servlet容器将自动关闭流.

例如,如果您关闭了流,则在实施过滤器时将无法使用该流.

说了这么多,如果你关闭它,只要你不再尝试使用它就不会发生任何不好的事情.

编辑:另一个过滤器链接

EDIT2:adrian.tarau是正确的,因为如果你想在servlet完成它之后改变响应,你应该创建一个包装器来扩展HttpServletResponseWrapper并缓冲输出.这是为了防止输出直接进入客户端,但是如果servlet关闭了流,也可以保护输出,如本摘录所述(强调我的):

修改响应的过滤器通常必须 在响应返回到客户端之前捕获响应.这样做的方法是将生成响应的servlet传递给一个替代流.备用流阻止servlet在完成时关闭原始响应流,并允许过滤器修改servlet的响应.

文章

从Sun官方文章中可以推断出,从servlet关闭输出流是正常现象,但不是强制性的.

  • 这是对的.需要注意的一点是,在某些情况下,您可能需要刷新流,这是完全允许的. (2认同)
  • 关闭编写器还有另一个副作用。关闭后,您也将无法通过 response.setStatus 设置状态代码。 (2认同)

ska*_*man 70

它们的一般规则是:如果你打开流,那么你应该关闭它.如果你没有,你不应该.确保代码是对称的.

在这种情况下HttpServletResponse,它的清晰度有点不太明显,因为调用getOutputStream()是一个打开流的操作并不明显.Javadoc只是说它" Returns a ServletOutputStream"; 同样的getWriter().无论哪种方式,很清楚的是HttpServletResponse"拥有"流/编写器,它(或容器)负责再次关闭它.

所以要回答你的问题 - 不,你不应该在这种情况下关闭流.容器必须这样做,如果你在它之前进入,你可能会在应用程序中引入微妙的错误.

  • "如果你打开了流,那么你应该关闭它.如果你没有,你就不应该" - 说得好 (10认同)
  • 感觉就像在学校董事会张贴的句子"如果你打开它,关闭它.如果你打开它,关掉它.如果你解锁它,锁定它.[...]" (2认同)

Ski*_*ead 5

如果有可能在“包含”资源上调用过滤器,则绝对不要关闭流。这将导致包含资源因“流关闭”异常而失败。


小智 5

反对关闭OutputStream. 看看这个servlet。它抛出异常。该异常在 web.xml 中映射到错误 JSP:\n

\n\n
package ser;\n\nimport java.io.*;\nimport javax.servlet.ServletException;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.*;\n\n@WebServlet(name = "Erroneous", urlPatterns = {"/Erroneous"})\npublic class Erroneous extends HttpServlet {\n\n  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {\n    resp.setContentType("text/html;charset=UTF-8");\n    PrintWriter out = resp.getWriter();\n    try {\n      throw new IOException("An error");\n    } finally {\n//      out.close();\n    }\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

web.xml 文件包含:\n

\n\n
<?xml version="1.0" encoding="UTF-8"?>\n<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">\n    <session-config>\n        <session-timeout>\n            30\n        </session-timeout>\n    </session-config>\n    <error-page>\n        <exception-type>java.io.IOException</exception-type>\n        <location>/error.jsp</location>\n    </error-page>\n</web-app>\n
Run Code Online (Sandbox Code Playgroud)\n\n

和错误.jsp:

\n\n
<%@page contentType="text/html" pageEncoding="UTF-8" isErrorPage="true"%>\n<!DOCTYPE html>\n<html>\n    <head>\n        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n        <title>Error Page</title>\n    </head>\n    <body>\n        <h1><%= exception.getMessage()%></h1>\n    </body>\n</html>\n
Run Code Online (Sandbox Code Playgroud)\n\n

当您在浏览器中加载时,/Erroneous您会看到显示“An error”的错误页面。\n但是,如果您取消注释out.close()上述 servlet 中的行,重新部署应用程序,然后重新加载/Erroneous\xe2\x80\x99,您将在浏览器中看不到任何内容。我不知道实际发生了什么,但我想这out.close()会阻止错误处理。

\n\n

使用 Netbeans 7.4 在 Tomcat 7.0.50、Java EE 6 上进行了测试。

\n