99

Java サーブレットでは、response.getOutputStream()またはを介し​​て応答本文にアクセスできますresponse.getWriter()。書き込まれた後に.close()これを呼び出す必要がありますか?OutputStream

一方では、常にOutputStreams を閉じるようにというブロッホ派の勧めがあります。一方、この場合、クローズする必要がある基になるリソースがあるとは思いません。ソケットの開閉は HTTP レベルで管理され、永続的な接続などを可能にします。

4

6 に答える 6

79

それらの一般的なルールは次のとおりです。ストリームを開いた場合は、それを閉じる必要があります。あなたがしなかったなら、すべきではありません。コードが対称であることを確認してください。

の場合、呼び出しがストリームを開く操作であるHttpServletResponseかどうかが明らかではないため、少し明確ではありません。getOutputStream()Javadoc には、「Returns a ServletOutputStream」とだけ書かれています。同様にgetWriter()。いずれにせよ、明らかなことはHttpServletResponse、ストリーム/ライターを「所有」しており、それ (またはコンテナー) が再びそれを閉じる責任があるということです。

あなたの質問に答えるために - いいえ、この場合、ストリームを閉じるべきではありません。コンテナーはそれを行う必要があり、その前にコンテナーに入ると、アプリケーションに微妙なバグが発生する危険があります。

于 2009-07-21T15:18:00.463 に答える
5

「含まれる」リソースでフィルターが呼び出される可能性がある場合は、絶対にストリームを閉じないでください。これにより、インクルード リソースが「ストリーム クローズ」例外で失敗します。

于 2010-10-15T17:58:54.990 に答える
4

ストリームを閉じる必要があります。getOutputStream()を呼び出し、ストリームがパラメーターとして渡されないため、コードはよりクリーンになります。通常は、ストリームを使用して閉じようとしない場合です。サーブレットAPIは、出力ストリームを閉じることができるか、閉じてはならない場合、この場合は安全にストリームを閉じることができるとは述べていません。サーブレットによって閉じられていない場合、そこにあるすべてのコンテナがストリームを閉じます。

Jettyのclose()メソッドは次のとおりです。ストリームが閉じられていない場合は閉じます。

public void close() throws IOException
    {
        if (_closed)
            return;

        if (!isIncluding() && !_generator.isCommitted())
            commitResponse(HttpGenerator.LAST);
        else
            flushResponse();

        super.close();
    }

また、フィルタの開発者は、OutputStreamが閉じられていないと想定しないでください。サーブレットがジョブを実行した後にコンテンツを変更する場合は、常に別のOutputStreamを渡す必要があります。

編集:私は常にストリームを閉じており、Tomcat/Jettyに問題はありませんでした。古いものでも新しいものでも、コンテナに問題はないと思います。

于 2009-07-21T15:08:26.253 に答える
4

を閉じることに対する別の議論OutputStream。このサーブレットを見てください。例外がスローされます。例外は 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()外し、アプリケーションを再デプロイしてリロード/Erroneousすると、ブラウザには何も表示されません。実際に何が起こっているのかはわかりませんがout.close()、エラー処理が妨げられていると思います。

Tomcat 7.0.50、Netbeans 7.4 を使用した Java EE 6 でテスト済み。

于 2014-02-19T15:42:38.297 に答える