Answers:
通常,您不应该关闭流。在servlet完成作为servlet请求生命周期的一部分运行之后,servlet容器将自动关闭流。
例如,如果您关闭流,那么在实现Filter的情况下将不可用。
说了这么多,只要您关闭它,只要您不尝试再次使用它,都不会发生任何不良情况。
编辑:另一个筛选器链接
EDIT2:adrian.tarau是正确的,因为如果您想在Servlet完成其操作后更改响应,则应创建一个扩展HttpServletResponseWrapper的包装器并缓冲输出。这是为了防止输出直接进入客户端,但也允许您保护servlet是否关闭流,如以下摘录(强调我的话):
修改响应的过滤器通常必须 在将响应返回给客户端之前捕获该响应。实现此目的的方法是将生成响应的servlet传递给替代流。替身流阻止servlet在完成时关闭原始响应流,并允许过滤器修改servlet的响应。
从Sun的官方文章可以推断出 OutputStream
从servlet属于正常现象,但不是强制性的。
它们的一般规则是:如果打开流,则应将其关闭。如果没有,就不应该。确保代码是对称的。
在的情况下HttpServletResponse
,它没有那么明确,因为调用getOutputStream()
是否是打开流的操作并不明显。Javadoc只是说“ Returns a ServletOutputStream
”;类似的getWriter()
。无论哪种方式,都清楚的是HttpServletResponse
流/写入器“拥有”,并且它(或容器)负责再次关闭它。
因此,请回答您的问题-不,在这种情况下,您不应该关闭流。容器必须做到这一点,如果您在此之前就进入了该容器,则可能会在应用程序中引入细微的错误。
close()
在流完成后调用时,客户端立即返回,其余servlet继续执行。那会不会使答案更具相对性?而不是确定的是或否
如果有可能在“包含”资源上调用过滤器,则绝对不要关闭流。这将导致包含资源因“流关闭”异常而失败。
您应该关闭流,因为调用getOutputStream()会使代码更简洁,并且通常不使用流就将其作为参数传递给您,而通常只使用它而不尝试关闭它。Servlet API并未声明如果可以关闭输出流或必须关闭输出流,在这种情况下,您可以安全地关闭流,如果该流没有被Servlet关闭,则其中的任何容器都将关闭该流。
这是Jetty中的close()方法,如果未关闭流,它们将关闭流。
public void close() throws IOException
{
if (_closed)
return;
if (!isIncluding() && !_generator.isCommitted())
commitResponse(HttpGenerator.LAST);
else
flushResponse();
super.close();
}
此外,作为Filter的开发人员,您不应假定未关闭OutputStream,如果要在Servlet完成其工作后更改内容,则应始终传递另一个OutputStream。
编辑:我总是关闭流,并且我对Tomcat / Jetty没有任何问题。我认为您对任何新旧容器都不应该有任何问题。
另一种反对关闭市场的论点OutputStream
。看一下这个servlet。引发异常。异常在web.xml中映射到错误JSP:
package ser;
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name = "Erroneous", urlPatterns = {"/Erroneous"})
public class Erroneous extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
try {
throw new IOException("An error");
} finally {
// out.close();
}
}
}
web.xml文件包含:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<error-page>
<exception-type>java.io.IOException</exception-type>
<location>/error.jsp</location>
</error-page>
</web-app>
和error.jsp:
<%@page contentType="text/html" pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error Page</title>
</head>
<body>
<h1><%= exception.getMessage()%></h1>
</body>
</html>
/Erroneous
在浏览器中加载时,您会看到显示“错误”的错误页面。但是,如果取消注释out.close()
上述servlet中的行,重新部署应用程序,然后重新加载,/Erroneous
您将在浏览器中看不到任何内容。我不知道实际发生了什么,但我想那是out.close()
可以防止错误处理。
使用Netbeans 7.4在Tomcat 7.0.50和Java EE 6上进行了测试。
close()
什么都不做的。什么,你应该做的是接近每一个可关闭的资源。