Java Servlet:提交响应后无法转发
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18211497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Servlet: Cannot forward after response has been committed
提问by tokhi
I'm working on servlet page that renders content based on geo-location
, and I want to use both sendRedirect
and forward
together; e.g; you browse example.com/aPage.jsp
from France
; first I want the servlet to redirect you to example.com/fr/aPage.jsp
and then forward you to the resources
page.
我工作的基础上呈现的内容servlet页面上geo-location
,我想同时使用sendRedirect
和forward
在一起; 例如; 您浏览example.com/aPage.jsp
的France
; 首先,我希望 servlet 将您重定向example.com/fr/aPage.jsp
到该resources
页面,然后将您转发到该页面。
This is what I have in my servlet:
这是我的 servlet 中的内容:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
....
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
// after redirect forward the resources page
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
...
}
But I get:
但我得到:
java.lang.IllegalStateException: Cannot forward after response has been committed
I know the error appears becauseI can't use both sendRedirect
and forward
one after another, but I don't know how to achieve what I want (as described above) without this.
我知道,因为出现错误,我不能同时使用sendRedirect
和forward
一个又一个,但我不知道该如何实现我想要的东西没有这个(如上所述)。
any help?
有什么帮助吗?
回答by nanofarad
Once you redirect, the servlet you're working on is no longer in control. You need to get the servlet that is the targetof the redirect to recognize the correct condition to forward and then call forward there, with similar code:
重定向后,您正在处理的 servlet 不再受控制。您需要获取作为重定向目标的 servlet以识别要转发的正确条件,然后在那里调用转发,使用类似的代码:
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
Even if it's the same servlet, it's a new invocation of the servlet's doGet(
or other similar method.
即使它是同一个 servlet,它也是对 servletdoGet(
或其他类似方法的新调用。
回答by Sotirios Delimanolis
When you call
你打电话时
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
you are sending your client a 302 HTTP status code with the location to redirect to. Your client then needs to make a new HTTP request to that location. Whichever Servlet is supposed to handle the path REDIRECT_URL_BASED_ON_GEO
should then use the RequestDispatcher
to forward to the resource described by RESOURCES_PAGE
.
您正在向您的客户端发送 302 HTTP 状态代码以及要重定向到的位置。然后,您的客户端需要向该位置发出新的 HTTP 请求。无论哪个 Servlet 应该处理路径,REDIRECT_URL_BASED_ON_GEO
都应该使用RequestDispatcher
转发到由 描述的资源RESOURCES_PAGE
。
To better explain your exception
为了更好地解释您的异常
java.lang.IllegalStateException: Cannot forward after response has been committed
a committed response is a response where HTTP headers are already sent. If we look at your code
已提交的响应是已发送 HTTP 标头的响应。如果我们查看您的代码
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
After this line, you've already sent the response along with the headers (302).
在此行之后,您已经将响应与标头 (302) 一起发送。
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
After these lines, you're asking the resource RESOURCES_PAGE
to finish processing the request. That includes writing HTTP headers and body. But the request has already been processed and a response has already been sent, so it will fail, throwing the exception.
在这些行之后,您要求资源RESOURCES_PAGE
完成对请求的处理。这包括编写 HTTP 标头和正文。但是请求已经被处理并且已经发送了响应,所以它会失败,抛出异常。
回答by Suresh Atta
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
// after redirect forward the resources page
After that line , Your response start writing to clinet.
在该行之后,您的回复开始写入 clinet。
And you are trying to add additional data to it.
您正在尝试向其中添加其他数据。
The server has already finishedwriting the response header and is writing the body of the content, and which point you are trying to write more to the header - of course it cant rewind.
服务器已经完成了响应标头的写入并正在写入内容的主体,并且您正在尝试向标头写入更多内容 - 当然它不能倒带。
So,Thumb rule while dealing with servlet is
所以,处理 servlet 时的拇指规则是
Finish your logic before redirect
or forward
add return statement.So execution ends there .
在之前完成您的逻辑 redirect
或forward
添加 return 语句。因此执行到此结束。
回答by Sir RotN
You have to be aware that a redirect is a complete response to the browser and the browser will in turn issue a new request to the url you redirected to. Even though you can't really sse it when dealing with the browser you always have to be aware that this is what happens.
您必须注意重定向是对浏览器的完整响应,浏览器将依次向您重定向到的 url 发出新请求。即使在与浏览器打交道时您无法真正理解它,您也必须始终意识到这就是发生的事情。
Now, if you use the same controller for the second request you have to check wether a redirect is necessary or you can now do the forward instead.
现在,如果您对第二个请求使用相同的控制器,您必须检查是否需要重定向,或者您现在可以改为执行转发。
if (!path.startsWith(locationPrefix)) {
response.sendRedirect(locationPrefix + path);
return;
} else {
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
return;
}
Of course it would be nicer to have a distinct controller per request, but depending of url structure and framework this is not always possible.
当然,每个请求有一个不同的控制器会更好,但取决于 url 结构和框架,这并不总是可行的。