Captcha servlet 导致 java.lang.IllegalStateException: PWC3999: 提交响应后无法创建会话
我正在使用 SimpleCaptcha 创建验证码输入,并对验证码输入进行验证。我使用以下代码创建了验证码输入。
HTML 代码:
<form action="submit_proceed.do" method="post">
<img src="captchaImg" /><input type="text" name="captcha" value=""><br />
<input type="submit" value="Submit" name="submit" />
</form>
JavaServlet 代码:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Iterator;
import nl.captcha.Captcha;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
List errorMsgs = new LinkedList();
try{
// Validate Captcha
HttpSession session = request.getSession(true);
String userCaptcha = request.getParameter("captcha");
Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);
if (!captcha.isCorrect(userCaptcha)) {
errorMsgs.add("Please input the correct Captcha value.");
}
} catch (RuntimeException e) {
errorMsgs.add("An unexpected error: " + e.getMessage());
RequestDispatcher view = request.getRequestDispatcher("/error.view");
view.forward(request, response);
}
但是我不断收到此错误:
StandardWrapperValve[Captcha]: PWC1406: Servlet.service() for servlet Captcha threw exception
java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed
如何在 servlet 上创建会话?我该如何解决这个问题?
非常感谢。
I am creating a CAPTCHA input using SimpleCaptcha, and did validation of the Captcha input. I am created a captcha input with the following codes.
HTML Code:
<form action="submit_proceed.do" method="post">
<img src="captchaImg" /><input type="text" name="captcha" value=""><br />
<input type="submit" value="Submit" name="submit" />
</form>
JavaServlet Code :
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Iterator;
import nl.captcha.Captcha;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
List errorMsgs = new LinkedList();
try{
// Validate Captcha
HttpSession session = request.getSession(true);
String userCaptcha = request.getParameter("captcha");
Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME);
if (!captcha.isCorrect(userCaptcha)) {
errorMsgs.add("Please input the correct Captcha value.");
}
} catch (RuntimeException e) {
errorMsgs.add("An unexpected error: " + e.getMessage());
RequestDispatcher view = request.getRequestDispatcher("/error.view");
view.forward(request, response);
}
However I kept getting this error:
StandardWrapperValve[Captcha]: PWC1406: Servlet.service() for servlet Captcha threw exception
java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed
How do I create a session on my servlet? How can I resolve this issue?
Thank you very much.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
异常消息非常清楚。有非法国家的手段。当响应已经提交时,您不能再设置/更改响应标头。当标头已发送到客户端时,将提交响应。这是一个无法返回的点。
每当输出流被直接刷新(输入)时,就会提交响应。当您向响应写入超过 2K 数据(具体取决于服务器配置)、手动执行
flush()
或执行sendRedirect()
调用时,就会发生这种情况。每当需要创建会话时,服务器都需要在响应标头中设置一个 cookie,以便它可以识别特定的客户端并将其与服务器内存中的 HttpSession 实例关联起来。但如果响应已提交,则这是不可能的,因此会出现此异常。
回到这个问题的根本原因:
这是
servlet-name
为Captcha
的 servlet 导致了此问题。您需要检查/调试整个请求-响应链,以查看哪些 servlet/过滤器全部被调用,以及其中哪些可能在Captcha
servlet 能够之前提交了响应创建会话。我无法为您提供更多帮助,因为您的 topicstart 中缺少此信息。至少,在目前给出的代码示例中,我发现您不必要调用
response.getWriter()
。我不确定现实世界的代码是什么样的,也许你已经删除了一些行,但很可能你实际上正在写入它,这可能是问题的根本原因。如果你写了太多或者刷新了它,那么响应将被提交。不要不要在 Servlet(应该是控制器)内写入响应。您通常使用 JSP 来实现这一点。或者,如果出于调试目的,请使用 stdout (System.out.println()
) 或 记录器。The exception message is pretty clear. There's means of an illegal state. You cannot set/change the response headers anymore when the response is already been committed. A response is committed when the headers are already been sent to the client side. This is a point of no return.
The response will be committed whenever the outputstream has been flushed (in)directly. That can happen when you write more than 2K to the response (depends on server config however), or did
flush()
manually, or did asendRedirect()
call.Whenever the session needs to be created, the server needs to set a cookie in the response header so that it can identify the particular client and associate it with a
HttpSession
instance in the server memory. But that's not possible if the response is already committed, hence this exception.Back to the root cause of this problem:
It is the servlet with the
servlet-name
ofCaptcha
which caused this problem. You need to check/debug the entire request-response chain to see which servlets/filters are all invoked and which of them might have committed the response before theCaptcha
servlet was able to create the session. I can't help you more further as this information is missing in your topicstart.At least, in the as far given code example, I see that you're unnecessarily calling
response.getWriter()
. I am not sure how the real world code look like, maybe you've stripped some lines, but chances are that you're actually writing to it and that might be the root cause of the problem. If you write too much or did a flush on it, then the resopnse will be committed. Do not write to the response inside a Servlet which is supposed to be a controller. There you normally use the JSP for. Or if it is for debugging purposes, use the stdout (System.out.println()
) or a Logger.有问题的代码位于
nl.captcha.servlet.SimpleCaptchaServlet
Servlet 中。如果将其更改为StickyCaptcha
,问题就会消失,但具体来说,以下是 SimpleCaptcha Servlet 中的违规行。实际上,代码正在将图像文件写入响应(通常大于默认的 2k)。
因此,您暂时可以使用
StickyCaptcha
或检查代码并解决问题。The offending code is in
nl.captcha.servlet.SimpleCaptchaServlet
Servlet. If you change it toStickyCaptcha
the problem will go away but specifically the following are the offending lines in SimpleCaptcha Servlet.Actually the code is writing the image file to response (which is usually greater than default 2k).
So for the time being you can use the
StickyCaptcha
or checkout the code and fix the issue.将此行:移动
到 doPost 方法中的第一条语句。
这应该有帮助。
Move this line:
to be first statement in doPost method.
This should help.
看来您在处理帖子之前已经将标头发送给客户端。如果创建会话,服务器需要将会话ID发送给客户端。这通常是通过发送 cookie 来完成的。我想您在将任何内容发送回客户端之前检查代码是否执行操作处理。
Seems, that you already sent the header to the client before handling the post. If you create a session, the server needs to send the session ID to the client. This is usually done by sending a cookie. I suppose you check your code for whether you execute the action handling before you send anything back to the client.
通过添加此创建会话
javax.servlet.http.HttpSession session = request.getSession();
create session by adding this
javax.servlet.http.HttpSession session = request.getSession();
此行
意味着在处理此特定请求之前会话应该已经存在,因此我想知道在发送原始表单之前您是否应该进行一些初始化。这应该由您正在使用的框架指定。
例如,您可能有一个初始 servlet,
您可以在 JSP 中完成所有这些操作,或者您可以将您的 servlet 转发到一个。
您可以检查一下这个 catcha 库的使用示例吗?
This line
implies that the session should already exist before this particular request is being processed, hence I wonder is there is some initialisation you are supposed to do before sending your original form. This should be specified by the framework your are using.
For example you might have an initial serlvet that
You could do that all in a JSP, or you could have your servlet forward to one.
Are there any examples of usage of this catcha library you could examine?