Forward() vs HttpServletResponse.sendRedirect()

forward()sendRedirect()在概念上的区别是什么?

155928 次浏览

RequestDispatcher接口允许您执行服务器端转发/包含,而 sendRedirect()执行客户端重定向。在客户端重定向中,服务器会发回一个 HTTP状态码的 302(临时重定向) ,这会导致网络浏览器在重定向位置发出一个全新的 HTTP GET请求。相反,当使用 RequestDispatcher接口时,包含/转发到新资源的操作完全在服务器端进行。

这两种方法中的任何一种都可能是“更好的”,也就是说,根据你想要做什么,更适合你。

服务器端重定向的速度更快,因为您可以从不同的页面获取数据,而无需往返于浏览器。但是在浏览器中看到的 URL 仍然是原始地址,所以这里有一点不一致。

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

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

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

你可以使用 web 浏览器的内置/插件开发工具集来跟踪它。点击 Chrome/IE9/Firebug 中的 F12,查看“网络”部分。

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

  • 客户端向 some.jsp发送一个 HTTP 请求。
  • 服务器发送一个包含 other.jsp内容的 HTTP 响应。

但是,由于原始 HTTP 请求是发送给 some.jsp的,因此浏览器地址栏中的 URL 保持不变。而且,在 some.jsp后面的控制器中设置的任何请求属性在 other.jsp中都是可用的。在重定向过程中不会发生这种情况,因为您基本上是强制客户机在 other.jsp上创建一个 新的 HTTP 请求,因此抛弃了 some.jsp上的原始请求,包括它的所有属性。


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

例如,您可以在 /WEB-INF/login.jsp中有一个 JSP 文件,在 /loginurl-pattern上映射一个 LoginServlet。当您调用 http://example.com/context/login时,将调用 servlet 的 doGet()。你可以在这里做任何 前情提要的处理工作,最后是 前进的请求,比如:

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

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

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

这样,servlet 的 doPost()将被调用,您可以在其中执行任何 邮寄处理工作(例如,验证、业务逻辑、登录用户等)。

如果有任何错误,那么您通常希望 前进请求返回到相同的页面,并在输入字段旁显示错误,以此类推。您可以使用 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模式

参见:

SendRedirect()将搜索服务器之间的内容。它的速度很慢,因为它必须通过发送内容的 URL 来使浏览器更加亲密。然后浏览器会在同一台服务器或另一台服务器中创建一个新的内容请求。

我认为 RquestDispatcher是用来搜索服务器内的内容的。它是服务器端进程,比 SendRedirect()方法更快。但问题是,它不会向服务器显示搜索所需的日期或内容的浏览器,也不会要求浏览器更改 URL 标签中的 URL。所以对使用者不会造成什么不便。

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

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

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

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

使用这个 BY,我们可以跨不同的服务器转发或包含请求或响应。在这种情况下,客户端在重定向页面时得到了提示,但在上述过程中,客户端不会得到提示

RequestDispatcher-forward ()方法

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

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

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

  4. 视觉上,我们不能看到转发的地址,它是透明的。

  5. 使用 forward()方法比使用 sendRedirect快。

  6. 当我们使用 forward 进行重定向,并且希望在新资源中使用相同的数据时,我们可以使用 request.setAttribute(),因为我们有一个可用的请求对象。

发送重定向

  1. 对于 sendRedirect,请求被传输到另一个资源、不同的域或者 不同的服务器进行进一步的处理。

  2. 使用 sendRedirect时,容器将请求传输到客户机或浏览器,因此在 sendRedirect方法中给出的 URL 可以作为新请求看到客户机。

  3. sendRedirect调用的情况下,旧的请求和响应对象将丢失,因为浏览器将其视为新的请求。

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

  5. sendRedirect比较慢,因为需要一次额外的往返,因为创建了一个全新的请求,而旧的请求对象丢失了。需要两个浏览器请求。

  6. 但是在 sendRedirect中,如果我们想要对一个新资源使用相同的数据,我们必须在会话中存储数据,或者将数据与 URL 一起传递。

哪个好?

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

如果您希望控制被传输到新的服务器或上下文,并且它被视为完全新的任务,那么我们使用 sendRedirect。 一般来说,如果在浏览器重新载入网页时可以安全地重复操作,并且不会影响结果,则应使用转发。

来源

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

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

对于其他场景,forward 的使用效率更高,因为它比 sendRedirect 更快

Forward ()和 sendRedirect ()方法之间的主要区别在于,如果是 forward () ,就会发生重定向 在服务器端,并不可见的客户端,但在情况下 SendRedirect () ,重定向发生在客户端,对于 客户端

enter image description here

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

前进() :

  1. forward()方法在服务器端执行。
  2. 请求被传输到同一服务器中的其他资源。
  3. 它不依赖于客户机的请求协议,因为 forward ()方法是由 servlet 容器提供的。
  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 中声明。