Servlet:响应提交后无法转发

我正在处理基于geo-location呈现内容的servlet页面,我想同时使用sendRedirectforward ; 例如; 你从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 

我知道错误出现是因为我不能同时使用sendRedirectforward ,但我不知道如何实现我想要的(如上所述)没有这个。

任何帮助?

  response.sendRedirect(REDIRECT_URL_BASED_ON_GEO); // after redirect forward the resources page 

在该行之后,您的响应开始写入clinet。

而您正在尝试向其添加其他数据。

服务器已经完成了编写响应头并正在编写内容的主体,并且您正在尝试向头部写更多内容 – 当然它无法倒回。

因此,处理servlet时的Thumb规则是

redirectforward之前完成逻辑添加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(或其他类似方法)的新调用。