我正在处理基于geo-location
呈现内容的servlet页面,我想同时使用sendRedirect
和forward
;例如;您从example.com/aPage.jsp
浏览France
;首先,我希望servlet将您重定向到example.com/fr/aPage.jsp
,然后转发到resources
页面。
这就是我在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);
...
}
但我明白了:
java.lang.IllegalStateException: Cannot forward after response has been committed
我知道错误出现是因为我不能一个接一个地使用sendRedirect
和forward
,但我不知道如何实现我想要的(如上所述)没有这个。
任何帮助?
答案 0 :(得分:4)
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
// after redirect forward the resources page
在该行之后,您的回复开始写入clinet。
您正在尝试向其中添加其他数据。
服务器有already finished编写响应标头并正在写入内容的正文,以及你试图在标题上写更多内容 - 当然它无法倒带。
因此,处理servlet时的Thumb规则是
在redirect
或forward
添加return语句之前完成逻辑。所以执行结束。
答案 1 :(得分:3)
致电时
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
您正在向您的客户端发送一个302 HTTP状态代码,其中包含要重定向到的位置。然后,您的客户端需要向该位置发出新的HTTP请求。无论哪个Servlet应该处理路径REDIRECT_URL_BASED_ON_GEO
,都应该使用RequestDispatcher
转发到RESOURCES_PAGE
描述的资源。
更好地解释您的例外
java.lang.IllegalStateException: Cannot forward after response has been committed
已提交的响应是已发送HTTP标头的响应。如果我们查看您的代码
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
在此行之后,您已经发送了响应以及标题(302)。
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
在这些行之后,您要求资源RESOURCES_PAGE
完成处理请求。这包括编写HTTP标头和正文。但是请求已经被处理并且已经发送了响应,因此它将失败,抛出异常。
答案 2 :(得分:1)
您必须知道重定向是对浏览器的完整响应,浏览器会依次向您重定向到的网址发出新请求。即使你在处理浏览器时无法真正理解它,你也必须意识到这就是发生的事情。
现在,如果您为第二个请求使用相同的控制器,则必须检查是否需要重定向,或者您现在可以执行转发。
if (!path.startsWith(locationPrefix)) {
response.sendRedirect(locationPrefix + path);
return;
} else {
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
return;
}
当然,每个请求都有一个独特的控制器会更好,但是根据网址结构和框架,这并不总是可行的。
答案 3 :(得分:0)
重定向后,您正在处理的servlet不再受控制。您需要获取重定向的目标的servlet,以识别要转发的正确条件,然后使用类似代码向前调用:
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
即使它是相同的servlet,它也是servlet的doGet(
或其他类似方法的新调用。