java.lang.IllegalStateException:提交响应后无法(转发 | sendRedirect | 创建会话) [英] java.lang.IllegalStateException: Cannot (forward | sendRedirect | create session) after response has been committed

查看:96
本文介绍了java.lang.IllegalStateException:提交响应后无法(转发 | sendRedirect | 创建会话)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个方法抛出

java.lang.IllegalStateException:提交响应后无法转发

java.lang.IllegalStateException: Cannot forward after response has been committed

我无法发现问题.有什么帮助吗?

and I am unable to spot the problem. Any help?

    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);
    }

推荐答案

初学者的一个常见误解是他们认为调用了 forward(), sendRedirect()sendError() 会神奇地退出并跳转";出方法块,特此忽略剩余的代码.例如:

A common misunderstanding among starters is that they think that the call of a forward(), sendRedirect(), or sendError() would magically exit and "jump" out of the method block, hereby ignoring the remnant of the code. For example:

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

因此这实际上不是真的.它们的行为肯定与任何其他 Java 方法没有什么不同(当然,System#exit() 除外).当上面示例中的 someConditiontrue 并且您因此在 sendRedirect() 之后调用 forward()sendError() 在同一个请求/响应上,那么你得到异常的机会很大:

This is thus actually not true. They do certainly not behave differently than any other Java methods (expect of System#exit() of course). When the someCondition in above example is true and you're thus calling forward() after sendRedirect() or sendError() on the same request/response, then the chance is big that you will get the exception:

java.lang.IllegalStateException:提交响应后无法转发

java.lang.IllegalStateException: Cannot forward after response has been committed

如果 if 语句调用了 forward() 并且您随后调用了 sendRedirect()sendError(),则抛出以下异常:

If the if statement calls a forward() and you're afterwards calling sendRedirect() or sendError(), then below exception will be thrown:

java.lang.IllegalStateException: 响应提交后无法调用 sendRedirect()

java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed

要解决此问题,您需要在之后添加 return; 语句

To fix this, you need either to add a return; statement afterwards

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

... 或者引入一个 else 块.

... or to introduce an else block.

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

要确定代码中的根本原因,只需搜索任何调用 forward()sendRedirect()sendError() 的行code> 而不退出方法块或跳过代码的剩余部分.这可以在特定代码行之前的同一 servlet 中,也可以在特定 servlet 之前调用的任何 servlet 或过滤器中.

To naildown the root cause in your code, just search for any line which calls a forward(), sendRedirect() or sendError() without exiting the method block or skipping the remnant of the code. This can be inside the same servlet before the particular code line, but also in any servlet or filter which was been called before the particular servlet.

对于 sendError(),如果您的唯一目的是设置响应状态,请改用 setStatus().

In case of sendError(), if your sole purpose is to set the response status, use setStatus() instead.

另一个可能的原因是 servlet 写入响应,而 forward() 将被调用,或者已经在完全相同的方法中被调用.

Another probable cause is that the servlet writes to the response while a forward() will be called, or has been called in the very same method.

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

响应缓冲区大小在大多数服务器中默认为 2KB,因此如果您向其中写入超过 2KB,那么它将被提交并且 forward() 将以同样的方式失败:

The response buffer size defaults in most server to 2KB, so if you write more than 2KB to it, then it will be committed and forward() will fail the same way:

java.lang.IllegalStateException:提交响应后无法转发

java.lang.IllegalStateException: Cannot forward after response has been committed

解决方案是显而易见的,只是不要在 servlet 中写入响应.这是 JSP 的责任.你只需像这样设置一个请求属性 request.setAttribute("data", "some string") 然后像这样 ${data} 在 JSP 中打印它.另请参阅我们的 Servlet 维基页面,了解如何正确使用 Servlet.

Solution is obvious, just don't write to the response in the servlet. That's the responsibility of the JSP. You just set a request attribute like so request.setAttribute("data", "some string") and then print it in JSP like so ${data}. See also our Servlets wiki page to learn how to use Servlets the right way.

另一个可能的原因是 servlet 将文件下载写入响应,然后例如一个 forward() 被调用.

Another probable cause is that the servlet writes a file download to the response after which e.g. a forward() is called.

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

这在技术上是不可能的.您需要删除 forward() 调用.最终用户将停留在当前打开的页面上.如果您真的打算在文件下载后更改页面,那么您需要将文件下载逻辑移动到目标页面的页面加载中.

This is technically not possible. You need to remove the forward() call. The enduser will stay on the currently opened page. If you actually intend to change the page after a file download, then you need to move the file download logic to page load of the target page.

另一个可能的原因是 forward()sendRedirect()sendError() 方法是通过嵌入在以老式方式<% scriptlets %>形式的JSP文件,这是一种自 2001 年起正式不鼓励.例如:

Yet another probable cause is that the forward(), sendRedirect() or sendError() methods are invoked via Java code embedded in a JSP file in form of old fashioned way <% scriptlets %>, a practice which was officially discouraged since 2001. For example:

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

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

这里的问题是 JSP 内部立即通过 out.write("<!DOCTYPE html> ... etc ...") 编写模板文本(即 HTML 代码)作为一旦遇到.因此,这与上一节中解释的问题本质上是相同的.

The problem here is that JSP internally immediately writes template text (i.e. HTML code) via out.write("<!DOCTYPE html> ... etc ...") as soon as it's encountered. This is thus essentially the same problem as explained in previous section.

解决方案是显而易见的,只是不要在 JSP 文件中编写 Java 代码.这是普通 Java 类(如 Servlet 或过滤器)的职责.另请参阅我们的 Servlet 维基页面,了解如何正确使用 Servlet.

Solution is obvious, just don't write Java code in a JSP file. That's the responsibility of a normal Java class such as a Servlet or a Filter. See also our Servlets wiki page to learn how to use Servlets the right way.

与您的具体问题无关,您的 JDBC 代码正在泄漏资源.也解决这个问题.有关提示,另请参阅 连接的频率,Statement 和 ResultSet 在 JDBC 中要关闭吗?

Unrelated to your concrete problem, your JDBC code is leaking resources. Fix that as well. For hints, see also How often should Connection, Statement and ResultSet be closed in JDBC?

这篇关于java.lang.IllegalStateException:提交响应后无法(转发 | sendRedirect | 创建会话)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆