RequestDispatcher.forward()vs HttpServletResponse.sendRedirect()

时间:2010-01-12 06:24:44

标签: jsp redirect servlets forward

forward()sendRedirect()之间的概念差异是什么?

10 个答案:

答案 0 :(得分:156)

在Web开发世界中,术语“重定向”是向客户端发送空HTTP响应的行为,其中只有Location标头,其中包含客户端必须向其发送全新GET请求的新URL 。所以基本上:

  • 客户端向some.jsp发送HTTP请求。
  • 服务器使用Location: other.jsp标题
  • 发回HTTP响应
  • 客户端向other.jsp发送HTTP请求(这反映在浏览器地址栏中!)
  • 服务器发回内容为other.jsp的HTTP响应。

您可以使用网络浏览器的内置/插件开发人员工具集进行跟踪。在Chrome / IE9 / Firebug中按F12,然后选中“网络”部分进行查看。

上述内容完全由sendRedirect("other.jsp")实现。 RequestDispatcher#forward()不会发送重定向。相反,它使用目标页面的内容作为HTTP响应。

  • 客户端向some.jsp发送HTTP请求。
  • 服务器发回内容为other.jsp的HTTP响应。

但是,由于原始HTTP请求是some.jsp,因此浏览器地址栏中的URL保持不变。


RequestDispatcher在MVC范例中非常有用,并且/或者当您想要隐藏JSP直接访问时。您可以将JSP放在/WEB-INF文件夹中,并使用Servlet来控制,预处理和后处理请求。 URL无法直接访问/WEB-INF文件夹中的JSP,但Servlet可以使用RequestDispatcher#forward()访问它们。

例如,您可以在/WEB-INF/login.jsp中创建一个JSP文件,并在LoginServlet url-pattern上映射/login。当您调用http://example.com/context/login时,将调用servlet的doGet()。你可以在那里做任何 pre 处理的东西,最后转发请求,如:

request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);

提交表单时,通常需要使用POST

<form action="login" method="post">

这样servlet的doPost()将被调用,你可以在那里做任何 post 处理(例如验证,业务逻辑,登录用户等)。

如果有任何错误,那么您通常希望将转发请求返回到同一页面,并在输入字段旁边显示错误,依此类推。您可以使用RequestDispatcher进行此操作。

如果POST成功,您通常需要重定向请求,以便在用户刷新请求时不会重新提交请求(例如按F5或导航回来在历史上)。

User user = userDAO.find(username, password);
if (user != null) {
    request.getSession().setAttribute("user", user); // Login user.
    response.sendRedirect("home"); // Redirects to http://example.com/context/home after succesful login.
} else {
    request.setAttribute("error", "Unknown login, please try again."); // Set error.
    request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to same page so that you can display error.
}

重定向因此指示客户端在给定的URL上触发新的GET请求。刷新请求只会刷新重定向的请求而不是初始请求。这将避免“双重提交”和混乱以及糟糕的用户体验。这也称为POST-Redirect-GET pattern

答案 1 :(得分:93)

  

requestDispatcher - forward()方法

     
      
  1. 当我们使用forward方法时,请求会转移到同一服务器中的另一个资源,以便进一步处理。

  2.   
  3. 对于forward,Web容器在内部处理所有处理,并且不涉及客户端或浏览器。

  4.   
  5. forward对象上调用requestDispatcher时,我们传递请求和响应对象,因此我们的旧请求对象出现在将要处理我们请求的新资源上。

  6.   
  7. 从视觉上看,我们无法看到转发的地址,它是透明的。

  8.   
  9. 使用forward()方法比sendRedirect更快。

  10.   
  11. 当我们使用转发重定向时,我们希望在新资源中使用相同的数据时,我们可以使用request.setAttribute(),因为我们有一个可用的请求对象。

  12.         

    的sendRedirect

         
        
    1. 如果是sendRedirect,请求会转移到其他资源,转移到其他域或转移到   不同的服务器进行进一步处理。

    2.   
    3. 当您使用sendRedirect时,容器会将请求传输到客户端或浏览器,因此sendRedirect方法中给出的URL作为对客户端的新请求可见。

    4.   
    5. 如果sendRedirect调用,旧请求和响应对象将丢失,因为它被浏览器视为新请求。

    6.   
    7. 在地址栏中,我们可以看到新的重定向地址。它不透明。

    8.   
    9. sendRedirect速度较慢,因为需要额外的往返行程,因为会创建一个全新的请求并丢失旧的请求对象。需要两个浏览器请求。

    10.   
    11. 但在sendRedirect中,如果我们想要使用,我们必须将数据存储在会话中或与URL一起传递。

    12.         

      哪一个好?

           

      它取决于哪种方法更有用的场景。

           

      如果您希望控件转移到新服务器或上下文,并将其视为全新任务,那么我们转到sendRedirect。   通常,如果在浏览器重新加载网页时可以安全地重复操作,并且不会影响结果,则应使用转发。

Source

答案 2 :(得分:19)

RequestDispatcher接口允许您执行服务器端转发/包含,而sendRedirect()执行客户端重定向。在客户端重定向中,服务器将发回HTTP状态代码302(临时重定向),这会导致Web浏览器对重定向位置的内容发出全新的HTTP GET请求。相反,当使用RequestDispatcher接口时,新资源的包含/转发完全在服务器端处理。

答案 3 :(得分:3)

这些方法中的任何一种都可能“更好”,即更合适,这取决于你想做什么。

如果您从不同的页面获取数据而不进行浏览器往返,则服务器端重定向会更快。但是在浏览器中看到的URL仍然是原始地址,因此您在那里创建了一点不一致。

客户端重定向功能更加通用,因为它可以将您发送到完全不同的服务器,或更改协议(例如,从HTTP到HTTPS),或两者兼而有之。浏览器知道新的URL。但它需要在服务器和客户端之间进行额外的反复。

答案 4 :(得分:3)

SendRedirect()将搜索服务器之间的内容。它很慢,因为它必须通过发送内容的URL来接近浏览器。然后,浏览器将在同一服务器或另一台服务器内创建新内容请求。

RquestDispatcher用于搜索我认为的服务器内的内容。它是服务器端进程,与SendRedirect()方法相比速度更快。但问题是,它不会在浏览器中查询所搜索的服务器所需的日期或内容,也不会要求浏览器更改URL选项卡中的URL。所以它不会给用户带来任何不便。

答案 5 :(得分:2)

  

forward()和sendRedirect()方法之间的主要区别在于,对于forward(),发生重定向   在服务器端,对客户端不可见,但是在   sendRedirect(),重定向发生在客户端,并且对   客户。

enter image description here

答案 6 :(得分:1)

如果我们需要将控制转移到不同的域或实现任务分离,则应使用技术上的重定向。

例如在支付应用程序中 我们首先执行PaymentProcess,然后重定向到displayPaymentInfo。如果客户端刷新浏览器,则只会再次执行displayPaymentInfo,并且不会重复PaymentProcess。但是如果我们在这种情况下使用forward,则PaymentProcess和displayPaymentInfo将按顺序重新执行,这可能会导致数据不存在。

对于其他方案,forward可以高效使用,因为它比sendRedirect

更快

答案 7 :(得分:0)

Request Dispatcher是一个接口,用于将请求或响应从Web资源分派到另一个Web资源。它主要包含两种方法。

  1. request.forward(req,res):此方法用于将请求从一个Web资源转发到另一个资源。即从一个servlet到另一个servlet,或从一个Web应用程序到另一个Web应用程序。

  2. response.include(req,res):此方法用于包括一个servlet对另一个servlet的响应

  3. 注意:通过使用Request Dispatcher,我们可以在同一服务器中转发或包含请求。

    request.sendRedirect():通过使用此功能,我们可以跨不同服务器转发或包含请求。在此,客户端在重定向页面时获得了一个暗示,但在上述过程中,客户端将无法获取信息

答案 8 :(得分:-1)

分派器允许请求数据从一个servlet传输到另一servlet。请求分派器的替代方法是发送重定向,但是对于每个新请求,发送重定向会在服务器中发生相反的请求分派器时返回到网络。

示例

Java中的Servlet调度程序 让我们通过简单的示例了解请求分配器的概念。考虑一下我们有三个名为servlet1,servlet2和Servlet3的servlet的情况。如果不使用分派器,则每当我们请求servlet1时,服务器就会将控制权传递给servlet1,此后,如果我们请求servlet2,则控制权将从servlet 1传递回服务器并传递给servlet2。在这种情况下,如果服务器位于印度,并且从美国请求servlet,则对于第二个请求,它必须返回到server(India),然后返回到servlet(America)。如果请求和响应之间的流量过大,则此选项不好。解决此问题的方法是调度程序。

Java中的Servlet调度程序 在相同的情况下,如果我们在服务器中使用调度程序,则控制权将从servlet1传递到servlet2,而无需返回服务器且不涉及网络。此概念也称为servlet链接。之所以称为servlet链接,是因为我们正在创建servlet请求的链,从servlet1到servlet2,从Servlet2到Servlet3,服务器将从servlet3获取数据。

数据传递

在servlet链中,不仅传递控制,而且数据也从一个servlet传输到另一个servlet,与发送重定向相比,它的主要优点是。在发送重定向中,每次获取新数据时,每个请求都是新请求。

考虑servlet1有一些应由servlet3执行的请求参数,然后数据可以从servlet1传输到servlet2,然后再从servlet2传输到servlet3,因此这里我们保留了从一个servlet到另一servlet的请求。

请求的寿命非常短,一旦我们获得响应,请求就结束了,但是这里的请求寿命可以从一个servlet保留到另一个。借助于此,我们可以将任务划分为许多servlet。

缺点

大多数时间分配器都是高效的,但在数据量大或我们根本不需要数据的情况下,或者在交易量低的情况下,可以有效地发送重定向工作。

答案 9 :(得分:-1)

Forward(ServletRequest request, ServletResponse response)sendRedirect(String url)之间的简单差异是

forward():

  1. forward()方法在服务器端执行。
  2. 请求已传输到同一服务器内的其他资源。
  3. 由于servlet容器提供了forward ()方法,因此它不依赖于客户端的请求协议。
  4. 请求由目标资源共享。
  5. 此方法仅消耗一次呼叫。
  6. 它可以在服务器内使用。
  7. 我们看不到转发的消息,它是透明的。
  8. forward()方法比sendRedirect()方法快。
  9. RequestDispatcher接口中声明。

sendRedirect():

  1. sendRedirect()方法在客户端执行。
  2. 请求已转移到其他资源到不同的服务器。
  3. sendRedirect()方法是在HTTP下提供的,因此只能与HTTP客户端一起使用。
  4. 已为目标资源创建了新请求。
  5. 消耗了两个请求和响应调用。
  6. 它可以在服务器内部和外部使用。
  7. 我们可以看到重定向的地址,它不是透明的。
  8. sendRedirect()方法比较慢,因为在创建新请求时,旧的请求对象会丢失。
  9. 它在HttpServletResponse中声明。