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