106

このメソッドはスローします

java.lang.IllegalStateException: 応答がコミットされた後に転送できません

そして私は問題を見つけることができません。何か助けはありますか?

    int noOfRows = Integer.parseInt(request.getParameter("noOfRows"));
    String chkboxVal = "";
    // String FormatId=null;
    Vector vRow = new Vector();
    Vector vRow1 = new Vector();
    String GroupId = "";
    String GroupDesc = "";
    for (int i = 0; i < noOfRows; i++) {
        if ((request.getParameter("chk_select" + i)) == null) {
            chkboxVal = "notticked";
        } else {
            chkboxVal = request.getParameter("chk_select" + i);
            if (chkboxVal.equals("ticked")) {
                fwdurl = "true";
                Statement st1 = con.createStatement();
                GroupId = request.getParameter("GroupId" + i);
                GroupDesc = request.getParameter("GroupDesc" + i);
                ResultSet rs1 = st1
                        .executeQuery("select FileId,Description from cs2k_Files "
                                + " where FileId like 'M%' and co_code = "
                                + ccode);
                ResultSetMetaData rsm = rs1.getMetaData();
                int cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol1 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol1.addElement(rs1.getObject(j));
                    }
                    vRow.addElement(vCol1);
                }
                rs1 = st1
                        .executeQuery("select FileId,NotAllowed from cs2kGroupSub "
                                + " where FileId like 'M%' and GroupId = '"
                                + GroupId + "'" + " and co_code = " + ccode);
                rsm = rs1.getMetaData();
                cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol2 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol2.addElement(rs1.getObject(j));
                    }
                    vRow1.addElement(vCol2);
                }

                // throw new Exception("test");

                break;
            }
        }
    }
    if (fwdurl.equals("true")) {
        // throw new Exception("test");
        // response.sendRedirect("cs2k_GroupCopiedUpdt.jsp") ;
        request.setAttribute("GroupId", GroupId);
        request.setAttribute("GroupDesc", GroupDesc);
        request.setAttribute("vRow", vRow);
        request.setAttribute("vRow1", vRow1);
        getServletConfig().getServletContext().getRequestDispatcher(
                "/GroupCopiedUpdt.jsp").forward(request, response);
    }
4

8 に答える 8

264

スターターの間でよくある誤解は、forward()sendRedirect()、またはの呼び出しsendError()が魔法のように終了し、メソッド ブロックから「ジャンプ」して、残りのコードを無視すると考えていることです。例えば:

protected void doXxx() {
    if (someCondition) {
        sendRedirect();
    }
    forward(); // This is STILL invoked when someCondition is true!
}

したがって、これは実際には正しくありません。もちろん、他の Java メソッドと異なる動作をすることはありません (System#exit()もちろん期待してください)。someCondition上記の例のように、同じ要求/応答の後または同じ要求/応答でtrue呼び出している場合、例外が発生する可能性が高くなります。forward()sendRedirect()sendError()

java.lang.IllegalStateException: 応答がコミットされた後に転送できません

ifステートメントが aforward()を呼び出し、その後sendRedirect()orを呼び出している場合sendError()、以下の例外がスローされます。

java.lang.IllegalStateException: 応答がコミットされた後に sendRedirect() を呼び出すことはできません

return;これを修正するには、後でステートメントを追加する必要があります

protected void doXxx() {
    if (someCondition) {
        sendRedirect();
        return;
    }
    forward();
}

... または、else ブロックを導入します。

protected void doXxx() {
    if (someCondition) {
        sendRedirect();
    } else {
        forward();
    }
}

コードの根本的な原因を突き止めるには、メソッド ブロックを終了したり、コードの残りをスキップしたりせずforward()に、を呼び出す行を検索するだけです。これは、特定のコード行の前の同じサーブレット内にある可能性がありますが、特定のサーブレットの前に呼び出されたサーブレットまたはフィルターにもあります。sendRedirect()sendError()

の場合sendError()、唯一の目的が応答ステータスを設定することである場合は、setStatus()代わりに を使用します。


もう 1 つの考えられる原因は、aforward()が呼び出されるか、まったく同じメソッドで呼び出されている間に、サーブレットが応答に書き込むことです。

protected void doXxx() {
    out.write("some string");
    // ... 
    forward(); // Fail!
}

ほとんどのサーバーでは、応答バッファーのサイズはデフォルトで 2KB に設定されているため、2KB を超える値を書き込むと、コミットされforward()て同じように失敗します。

java.lang.IllegalStateException: 応答がコミットされた後に転送できません

解決策は明らかです。サーブレットの応答に書き込まないでください。それは JSP の責任です。so のようにリクエスト属性を設定し、request.setAttribute("data", "some string")それを so のように JSP で出力するだけ${data}です。サーブレットの正しい使用方法については、サーブレットの wiki ページも参照してください。


もう 1 つの考えられる原因は、サーブレットがファイルのダウンロードを応答に書き込んでから、たとえば aforward()が呼び出されたことです。

protected void doXxx() {
    out.write(bytes);
    // ... 
    forward(); // Fail!
}

これは技術的に不可能です。通話を削除する必要がありforward()ます。エンドユーザーは、現在開いているページにとどまります。ファイルのダウンロード後に実際にページを変更する場合は、ファイルのダウンロード ロジックをターゲット ページのページ ロードに移動する必要があります。


さらに別の考えられる原因はforward()sendRedirect()またはメソッドが、2001 年以降公式に推奨さsendError()れていない旧式の方法で JSP ファイルに埋め込まれた Java コードを介して呼び出されること<% scriptlets %>です。例えば:

<!DOCTYPE html>
<html lang="en">
    <head>
        ... 
    </head>
    <body>
        ...

        <% sendRedirect(); %>
        
        ...
    </body>
</html>

ここでの問題は、JSP がテンプレート テキスト (つまり、HTML コード) を検出out.write("<!DOCTYPE html> ... etc ...")するとすぐに内部的に書き込むことです。したがって、これは基本的に前のセクションで説明した問題と同じです。

解決策は明らかです。JSP ファイルに Java コードを記述しないでください。これは、サーブレットやフィルターなどの通常の Java クラスの役割です。サーブレットの正しい使用方法については、サーブレットの wiki ページも参照してください。


以下も参照してください。


具体的な問題とは関係なく、JDBC コードがリソースをリークしています。それも修正してください。ヒントについては、「JDBC で Connection、Statement、および ResultSet を閉じる頻度はどれくらいですか?」も参照してください。

于 2010-01-23T22:51:07.430 に答える
20

return ステートメントを追加しても、この例外が発生します。これに対する唯一の解決策は、次のコードです。

if(!response.isCommitted())
// Place another redirection
于 2013-02-23T19:44:02.800 に答える
6

通常、このエラーは、既にリダイレクトを行ってから出力ストリームにさらにデータを出力しようとした後に表示されます。過去にこれを見た場合、多くの場合、ページをリダイレクトしようとしているフィルターの 1 つであり、その後もサーブレットに転送されます。サーブレットにすぐに問題があることはわかりません。そのため、設定しているフィルターも確認してみてください。

編集: 問題の診断に役立つ情報がいくつかあります…</p>

この問題を診断するための最初のステップは、例外がスローされている場所を正確に確認することです。ラインで投げられていると仮定しています

getServletConfig().getServletContext()
                  .getRequestDispatcher("/GroupCopiedUpdt.jsp")
                  .forward(request, response);

しかし、転送を試みた後に出力ストリームに出力しようとしているコードの後半でスローされていることに気付くかもしれません。上記の行から来ている場合は、この行の前のどこかに次のいずれかがあることを意味します。

  1. 出力ストリームにデータを出力する、または
  2. 事前に別のリダイレクトを行ってください。

幸運を!

于 2010-01-23T14:50:25.887 に答える
2

I removed

        super.service(req, res);

Then it worked fine for me

于 2015-08-14T07:21:16.500 に答える
2

これは、サーブレットが存在しないリクエスト オブジェクトにアクセスしようとしているためです。サーブレットの forward または include ステートメントは、メソッド ブロックの実行を停止しません。他の Java メソッドと同様に、メソッド ブロックまたは最初の return ステートメントの最後まで続きます。

この問題を解決する最善の方法は、ロジックに従って動的にページ (リクエストを転送すると思われる場所) を設定することです。あれは:

protected void doPost(request , response){
String returnPage="default.jsp";
if(condition1){
 returnPage="page1.jsp";
}
if(condition2){
   returnPage="page2.jsp";
}
request.getRequestDispatcher(returnPage).forward(request,response); //at last line
}

最後の行で一度だけ転送を行います...

各 forward() の後に return ステートメントを使用してこの問題を修正するか、各 forward() を if...else ブロックに入れることもできます

于 2014-11-20T17:59:18.767 に答える
2

フローを転送またはリダイレクトしているときに、 returnステートメントを追加する必要があります。

例:

前向きなら、

    request.getRequestDispatcher("/abs.jsp").forward(request, response);
    return;

リダイレクトする場合、

    response.sendRedirect(roundTripURI);
    return;
于 2012-08-19T07:16:00.893 に答える