java.lang.IllegalStateException:提交响应后无法(转发 | sendRedirect | 创建会话)
这个方法抛出
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
forward
/sendRedirect
/sendError
不要退出该方法!初学者中一个常见的误解是,他们认为调用
forward()
、sendRedirect()
或sendError()
方法会神奇地退出并“跳”出方法块,从而忽略代码的剩余部分。例如在 servlet 中:或者在过滤器中:
因此这实际上是不正确的。它们的行为当然与任何其他 Java 方法没有什么不同(当然,
System#exit()
除外)。当上例中的someCondition
为true
并且您因此在之后调用forward()
或doFilter()
在同一个请求/响应上使用sendRedirect()
或sendError()
,那么您收到异常的机会就大:这也适用于相反的条件。如果
if
语句调用forward()
并且您随后调用sendRedirect()
或sendError()
,那么可以抛出以下异常:要解决此问题,您需要随后添加一个
return;
语句...或引入一个 else 块。
要确定代码中的根本原因,只需搜索调用
forward()
、sendRedirect()
或sendError()
的任何行,而无需退出方法块或跳过代码的剩余部分。这可以位于特定代码行之前的同一 servlet 内,也可以位于在特定 servlet 之前调用的任何 servlet 或过滤器中。对于
sendError()
,如果您的唯一目的是设置响应状态,请改用setStatus()
。不要在
forward
/sendRedirect
/sendError
之前写入任何字符串另一个可能的原因是 servlet 在
forward( )
将被调用,或者已经在相同的方法中被调用。大多数服务器中的响应缓冲区大小默认为 2KB,因此如果您向其写入超过 2KB,那么它将被提交,并且
forward()
将以同样的方式失败:解决方案很明显,只需不要将 HTML 块写入 servlet 中的响应即可。这是 JSP 的职责。您只需设置一个请求属性,如
request.setAttribute("data", "some string")
,然后在 JSP 中打印它,如${data}
。另请参阅我们的 Servlet wiki 页面,了解如何正确使用 Servlet。在
forward
/sendRedirect
/sendError
之前不要写入任何文件另一个可能的原因是 servlet 将文件下载写入响应,之后例如调用
forward()
。这在技术上是不可能的。您需要删除
forward()
调用。最终用户将停留在当前打开的页面上。如果您确实打算在文件下载后更改页面,那么最好的选择是将 cookie 添加到响应中,并在由下载链接/按钮触发的 JavaScript 片段中轮询它。另请参阅 如何在生成后发送重定向在 Servlet 中生成文件下载。另一种方法是将文件下载逻辑移至目标页面的页面加载。基本上:首先使用此答案中提到的方式在磁盘上创建一个临时文件 如何在基于 servlet 的 Web 应用程序中临时保存生成的文件,然后使用文件名/标识符作为请求参数发送重定向,并在目标页面中根据条件进行打印该请求参数的存在
会立即通过此答案中提到的方式之一下载临时文件 最简单的方法在 Java Web 应用程序中提供来自应用程序服务器外部的静态数据。
不要在 JSP 中调用
forward
/sendRedirect
/sendError
另一个可能的原因是
forward()
, < code>sendRedirect() 或sendError()
方法通过嵌入在 JSP 文件中的 Java 代码以老式方式<% scriptlets %>
的形式调用>,这种做法自 2003 年起就被官方禁止。例如:这里的问题是 JSP 内部立即通过
out.write(" ... etc ...")
写入模板文本(即 HTML 代码)是遇到了。因此,这本质上是与上一节中解释的问题相同的问题。解决方案很明显,只要不要在 JSP 文件中编写 Java 代码即可。这是普通 Java 类(例如 Servlet 或 Filter)的职责。另请参阅我们的 Servlet wiki 页面,了解如何正确使用 Servlet。
另请参阅:
与您的具体问题无关,您的 JDBC 代码正在泄漏资源。也解决这个问题。有关提示,另请参阅连接的频率、Statement 和 ResultSet 在 JDBC 中要关闭吗?
forward
/sendRedirect
/sendError
do NOT exit the method!A common misunderstanding among starters is that they think that the call of a
forward()
,sendRedirect()
, orsendError()
method would magically exit and "jump" out of the method block, hereby ignoring the remnant of the code. For example in a servlet:Or in a filter:
This is thus actually not true. They do certainly not behave differently than any other Java methods (expect of
System#exit()
of course). When thesomeCondition
in above example istrue
and you're thus callingforward()
ordoFilter()
aftersendRedirect()
orsendError()
on the same request/response, then the chance is big that you will get the exception:This also applies to the inverse condition. If the
if
statement calls aforward()
and you're afterwards callingsendRedirect()
orsendError()
, then below exception can be thrown:To fix this, you need either to add a
return;
statement afterwards... or to introduce an else block.
To naildown the root cause in your code, just search for any line which calls a
forward()
,sendRedirect()
orsendError()
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.In case of
sendError()
, if your sole purpose is to set the response status, usesetStatus()
instead.Do not write any string before
forward
/sendRedirect
/sendError
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.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:Solution is obvious, just don't write chunks of HTML 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.Do not write any file before
forward
/sendRedirect
/sendError
Another probable cause is that the servlet writes a file download to the response after which e.g. a
forward()
is called.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 your best bet is to add a cookie to the response and poll for it in a piece of JavaScript which is triggered by the download link/button. See also How to send a redirect after generating a file download in Servlet.The alternative is to move the file download logic to page load of the target page. Basically: first create a temporary file on disk using the way mentioned in this answer How to save generated file temporarily in servlet based web application, then send a redirect with the file name/identifier as request param, and in the target page conditionally print based on the presence of that request param a
<script>window.location='...';</script>
which immediately downloads the temporary file via one of the ways mentioned in this answer Simplest way to serve static data from outside the application server in a Java web application.Do not call
forward
/sendRedirect
/sendError
in JSPYet another probable cause is that the
forward()
,sendRedirect()
orsendError()
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 2003. For example: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.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.
See also:
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?
即使添加 return 语句也会引发此异常,唯一的解决方案是以下代码:
even adding a return statement brings up this exception, for which only solution is this code:
通常,您在完成重定向后会看到此错误,然后尝试将更多数据输出到输出流。在我过去看到过这种情况的情况下,通常是过滤器之一尝试重定向页面,然后仍然转发到 servlet。我无法立即发现 servlet 存在任何问题,因此您可能还想尝试查看您已安装的任何过滤器。
编辑:诊断问题的更多帮助...
诊断此问题的第一步是确定抛出异常的确切位置。我们假设它是由该行抛出的
,但是您可能会发现它是在代码中稍后抛出的,在您尝试执行转发之后,您试图输出到输出流。如果它来自上面的行,那么这意味着在该行之前的某个地方您有:
祝你好运!
Typically you see this error after you have already done a redirect and then try to output some more data to the output stream. In the cases where I have seen this in the past, it is often one of the filters that is trying to redirect the page, and then still forwards through to the servlet. I cannot see anything immediately wrong with the servlet, so you might want to try having a look at any filters that you have in place as well.
Edit: Some more help in diagnosing the problem…
The first step to diagnosing this problem is to ascertain exactly where the exception is being thrown. We are assuming that it is being thrown by the line
But you might find that it is being thrown later in the code, where you are trying to output to the output stream after you have tried to do the forward. If it is coming from the above line, then it means that somewhere before this line you have either:
Good luck!
碰撞...
我刚刚遇到了同样的错误。我注意到我在重写 doPost() 方法以及显式调用超类构造函数时调用了 super.doPost(request, response);
当我注释掉时
doPost()
语句中的super.doPost(request, response);
运行得很好......不用说,我需要重新阅读
super() 最佳实践:p
Bump...
I just had the same error. I noticed that I was invoking
super.doPost(request, response);
when overriding thedoPost()
method as well as explicitly invoking the superclass constructorAs soon as I commented out the
super.doPost(request, response);
from withindoPost()
statement it worked perfectly...Needless to say, I need to re-read on
super()
best practices :p您应该在转发或重定向流时添加 return 语句。
示例:
如果转发,
如果重定向,
You should add return statement while you are forwarding or redirecting the flow.
Example:
if forwardind,
if redirecting,
这是因为您的 servlet 正在尝试访问不再存在的请求对象。
servlet 的forward 或include 语句不会停止方法块的执行。它像任何其他 java 方法一样继续到方法块的末尾或第一个返回语句。
解决此问题的最佳方法只是根据您的逻辑动态设置页面(您假设转发请求的位置)。也就是说:
并且在最后一行只执行一次转发...
您还可以在每个forward()之后使用return语句来解决这个问题,或者将每个forward()放在if...else块中
This is because your servlet is trying to access a request object which is no more exist..
A servlet's forward or include statement does not stop execution of method block. It continues to the end of method block or first return statement just like any other java method.
The best way to resolve this problem just set the page (where you suppose to forward the request) dynamically according your logic. That is:
and do the forward only once at last line...
you can also fix this problem using return statement after each forward() or put each forward() in if...else block
我删除了
然后它对我来说效果很好
I removed
Then it worked fine for me
在 returnforward 方法之后,您可以简单地执行以下操作:
它将打破当前范围。
After return forward method you can simply do this:
It will break the current scope.
如果您在基于 Spring 的 Web 应用程序上看到此情况,请确保您的方法使用 @ResponseBody 进行注释,或者控制器使用 @RestController 而不是 @Controller 进行注释。如果方法返回 JSON,但尚未配置为将其作为响应,它也会抛出此异常,Spring 将转而查找 jsp 页面来渲染并抛出此异常。
If you see this on a Spring based web application, make sure you have your method annotated with @ResponseBody or the controller annotated with @RestController instead of @Controller. It will also throw this exception if a method returns JSON, but has not been configured to have that as the response, Spring will instead look for a jsp page to render and throw this exception.