forward()
和之间的概念区别是什么sendRedirect()
?
9 回答
在 Web 开发世界中,术语“重定向”是向客户端发送一个空的 HTTP 响应的行为,该响应仅包含一个Location
包含客户端必须向其发送全新 GET 请求的新 URL 的标头。所以基本上:
- 客户端向
some.jsp
. - 服务器发回带有
Location: other.jsp
标头的 HTTP 响应 - 客户端发送一个 HTTP 请求
other.jsp
(这会反映在浏览器地址栏中!) - 服务器发回 HTTP 响应,内容为
other.jsp
.
您可以使用网络浏览器的内置/插件开发工具集对其进行跟踪。在 Chrome/IE9/Firebug 中按 F12 并检查“网络”部分以查看它。
以上正是通过 实现的sendRedirect("other.jsp")
。RequestDispatcher#forward()
不发送重定向。相反,它使用目标页面的内容作为 HTTP 响应。
- 客户端向
some.jsp
. - 服务器发回 HTTP 响应,内容为
other.jsp
.
但是,由于最初的 HTTP 请求是 to some.jsp
,所以浏览器地址栏中的 URL 保持不变。此外,在后面的控制器中设置的任何请求属性some.jsp
都将在other.jsp
. 这在重定向期间不会发生,因为您基本上是在强制客户端在 上创建一个新的HTTP 请求other.jsp
,从而丢弃some.jsp
包含其所有属性的原始请求。
这RequestDispatcher
在 MVC 范例中和/或当您想要隐藏 JSP 以防止直接访问时非常有用。您可以将 JSP 放在/WEB-INF
文件夹中,并使用Servlet
它来控制、预处理和后处理请求。文件夹中的 JSP/WEB-INF
不能通过 URL 直接访问,但Servlet
可以使用RequestDispatcher#forward()
.
例如,您可以有一个 JSP 文件,/WEB-INF/login.jsp
其中一个LoginServlet
映射到一个url-pattern
of 上/login
。当您调用 时,将调用http://example.com/context/login
servlet 。doGet()
您可以在那里进行任何预处理,最后转发请求,例如:
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
当您提交表单时,您通常希望使用POST
:
<form action="login" method="post">
这样,servletdoPost()
将被调用,您可以在其中进行任何后期处理(例如验证、业务逻辑、登录用户等)。
如果有任何错误,那么您通常希望将请求转发回同一页面并在输入字段旁边显示错误,依此类推。你可以使用RequestDispatcher
这个。
如果 aPOST
成功,您通常希望重定向请求,以便在用户刷新请求时不会重新提交请求(例如按 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.
}
因此,重定向GET
指示客户端在给定 URL 上触发新请求。刷新请求只会刷新重定向的请求,而不是初始请求。这将避免“双重提交”和混乱以及糟糕的用户体验。这也称为POST-Redirect-GET
模式。
也可以看看:
requestDispatcher - forward() 方法
当我们使用该
forward
方法时,请求被转移到同一服务器内的另一个资源进行进一步处理。在 的情况下
forward
,Web 容器在内部处理所有处理,不涉及客户端或浏览器。当
forward
在requestDispatcher
对象上调用时,我们传递请求和响应对象,因此我们的旧请求对象出现在将处理我们的请求的新资源上。从视觉上看,我们看不到转发的地址,它是透明的。
使用该
forward()
方法比sendRedirect
.当我们使用 forward 重定向,并且我们想在新资源中使用相同的数据时,我们可以使用
request.setAttribute()
,因为我们有一个可用的请求对象。发送重定向
在 的情况下
sendRedirect
,请求将被转移到另一个资源、不同的域或不同的服务器以进行进一步处理。当您使用
sendRedirect
时,容器将请求传输到客户端或浏览器,因此sendRedirect
方法内部给出的 URL 作为对客户端的新请求可见。在
sendRedirect
调用的情况下,旧的请求和响应对象会丢失,因为它被浏览器视为新请求。在地址栏中,我们可以看到新的重定向地址。它不透明。
sendRedirect
速度较慢,因为需要一个额外的往返,因为创建了一个全新的请求并且丢失了旧的请求对象。需要两个浏览器请求。但是
sendRedirect
,如果我们想为新资源使用相同的数据,我们必须将数据存储在会话中或与 URL 一起传递。哪一个好?
它取决于哪种方法更有用的场景。
如果您希望将控制权转移到新的服务器或上下文,并将其视为全新的任务,那么我们选择
sendRedirect
. 通常,如果在浏览器重新加载网页时可以安全地重复操作并且不会影响结果,则应使用转发。
该RequestDispatcher
界面允许您执行服务器端转发/包含,而sendRedirect()
客户端重定向。在客户端重定向中,服务器将发送回一个 HTTP 状态代码302
(临时重定向),这会导致 Web 浏览器在重定向位置为内容发出全新的 HTTPGET
请求。相反,当使用RequestDispatcher
接口时,包含/转发到新资源完全在服务器端处理。
这些方法中的任何一种都可能“更好”,即更合适,这取决于您想要做什么。
服务器端重定向速度更快,因为您可以从不同的页面获取数据,而无需往返浏览器。但是在浏览器中看到的 URL 仍然是原始地址,所以你在那里创建了一些不一致的地方。
客户端重定向更加通用,因为它可以将您发送到完全不同的服务器,或更改协议(例如从 HTTP 到 HTTPS),或两者兼而有之。并且浏览器知道新的 URL。但是服务器和客户端之间需要额外的来回。
SendRedirect()
将搜索服务器之间的内容。它很慢,因为它必须通过发送内容的 URL 来提示浏览器。然后浏览器将在同一服务器或另一台服务器中为内容创建一个新请求。
RquestDispatcher
我认为是用于搜索服务器内的内容。它是服务器端进程,与该方法相比它更快SendRedirect()
。但问题是它不会提示浏览器在哪个服务器中搜索所需的日期或内容,也不会要求浏览器更改 URL 选项卡中的 URL。因此对用户造成的不便很小。
如果我们需要将控制权转移到不同的域或实现任务分离,从技术上讲应该使用重定向。
例如,在支付应用程序中,我们首先执行 PaymentProcess,然后重定向到 displayPaymentInfo。如果客户端刷新浏览器,只会再次执行 displayPaymentInfo 并且不会重复 PaymentProcess。但是如果我们在这种场景下使用forward,PaymentProcess和displayPaymentInfo都会依次重新执行,可能会导致数据不一致。
对于其他情况,forward 使用起来很有效,因为它比 sendRedirect 更快
Request Dispatcher 是一个接口,用于将来自 Web 资源的请求或响应分派到另一个 Web 资源。它主要包含两种方法。
request.forward(req,res)
:此方法用于将请求从一个 Web 资源转发到另一个资源。即从一个servlet 到另一个servlet 或从一个web 应用程序到另一个web 应用程序。response.include(req,res)
:此方法用于包括一个 servlet 对另一个 servlet 的响应
注意:通过使用 Request Dispatcher,我们可以在同一服务器中转发或包含请求或响应。
request.sendRedirect()
:通过使用它,我们可以转发或包含跨不同服务器的请求或响应。在这种情况下,客户端在重定向页面时会收到提示,但在上述过程中,客户端不会收到提示
Forward(ServletRequest request, ServletResponse response)
和之间的简单区别sendRedirect(String url)
是
向前():
- 该
forward()
方法在服务器端执行。 - 请求被转移到同一服务器内的其他资源。
- 它不依赖于客户端的请求协议,因为该
forward ()
方法由 servlet 容器提供。 - 该请求由目标资源共享。
- 此方法只消耗一个调用。
- 它可以在服务器中使用。
- 我们看不到转发的消息,它是透明的。
- 方法比方法
forward()
快sendRedirect()
。 - 它在
RequestDispatcher
接口中声明。
发送重定向():
- sendRedirect() 方法在客户端执行。
- 请求被转移到其他资源到不同的服务器。
- sendRedirect() 方法是在 HTTP 下提供的,因此它只能用于 HTTP 客户端。
- 为目标资源创建新请求。
- 消耗了两个请求和响应调用。
- 它可以在服务器内部和外部使用。
- 我们可以看到重定向的地址,它是不透明的。
- sendRedirect() 方法较慢,因为创建新请求时旧请求对象丢失。
- 它在 HttpServletResponse 中声明。