【问题标题】:Servlet: Cannot forward after response has been committedServlet:提交响应后无法转发
【发布时间】:2013-08-15 05:04:03
【问题描述】:

我正在处理基于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,但是我不知道如何实现我想要的(如上所述)没有这个。

有什么帮助吗?

【问题讨论】:

    标签: java servlets geolocation response.redirect forward


    【解决方案1】:
     response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
      // after redirect forward the resources page
    

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

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

    服务器有already finished 写入响应标头并正在写入内容的主体,而您正在尝试向标头写入更多内容 - 当然它不能倒带。

    所以,处理 servlet 时的拇指规则是

    redirectforward添加return语句之前完成你的逻辑。所以执行到这里结束。

    【讨论】:

      【解决方案2】:

      当你打电话时

      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 标头和正文。但是请求已经被处理,并且已经发送了响应,所以会失败,抛出异常。

      【讨论】:

      • 在我的第一段中,让处理重定向的 servlet(因此映射到 REDIRECT_URL_BASED_ON_GEO)转发到您的资源。
      • 你的意思是我应该使用两个不同的servlet,一个用于REDIRECT_URL_BASED_ON_GEO,一个用于转发?
      • Servlet 映射到 URL。您的第一个 servlet 应该处理 url example.com/aPage.jsp,确定您在法国,然后重定向到不同的 url example.com/fr/aPage.jsp。然后另一个 Servlet 可以处理该 url 并转发到 resources page 资源。
      【解决方案3】:

      您必须知道重定向是对浏览器的完整响应,浏览器会反过来向您重定向到的 url 发出新请求。即使在与浏览器打交道时您无法真正了解它,您也必须始终意识到这就是发生的事情。

      现在,如果您对第二个请求使用相同的控制器,您必须检查是否需要重定向,或者您现在可以执行转发。

      if (!path.startsWith(locationPrefix)) {
        response.sendRedirect(locationPrefix + path);
        return;
      } else {
        RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
        view.forward(request, response);
        return;
      }
      

      当然,每个请求都有一个不同的控制器会更好,但根据 url 结构和框架,这并不总是可行的。

      【讨论】:

        【解决方案4】:

        一旦您重定向,您正在处理的 servlet 将不再受控制。您需要获取作为重定向的 目标 的 servlet,以识别正确的转发条件,然后在那里调用 forward,代码类似:

        RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
        view.forward(request, response);
        

        即使是同一个 servlet,也是对 servlet 的doGet( 或其他类似方法的新调用。

        【讨论】:

          猜你喜欢
          • 2013-06-25
          • 2023-03-17
          • 1970-01-01
          • 2011-12-18
          • 1970-01-01
          • 2014-05-09
          • 1970-01-01
          • 2015-01-27
          • 2013-09-15
          相关资源
          最近更新 更多