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

查看:261
本文介绍了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()sendError()之后调用forward(),则您获得 big 的机会很大将得到异常:

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()的行,而无需退出方法块或跳过代码的剩余部分.它可以在特定代码行之前的同一个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.

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

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 Wiki页面,以了解如何正确使用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()方法是通过嵌入JSP文件中的Java代码以老式方式<% scriptlets %>调用的,这种做法是.例如:

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或Filter)的责任.另请参见我们的Servlet Wiki页面,以了解如何正确使用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天全站免登陆