Servlet:响应提交后无法转发

时间:2013-08-13 14:12:53

标签: java servlets geolocation response.redirect forward

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

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

任何帮助?

4 个答案:

答案 0 :(得分:4)

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

在该行之后,您的回复开始写入clinet。

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

  

服务器有already finished编写响应标头并正在写入内容的正文,以及你试图在标题上写更多内容 - 当然它无法倒带。

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

redirectforward添加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(或其他类似方法的新调用。