forward()
和sendRedirect()
之间的概念差异是什么?
requestDispatcher - forward()方法
- 当我们使用
forward
方法时,请求被转移到同一服务器内的另一个资源以进行进一步处理。- 对于
forward
,Web容器在内部处理所有处理,并且不涉及客户端或浏览器。- 当在
forward
object上调用requestDispatcher
时,我们传递请求和响应对象,因此我们的旧请求对象出现在将要处理我们的请求的新资源上。- 在视觉上,我们无法看到转发的地址,它是透明的。
- 使用
forward()
方法比sendRedirect
更快。- 当我们使用forward重定向,并且我们想在新资源中使用相同的数据时,我们可以使用
request.setAttribute()
,因为我们有一个可用的请求对象。的sendRedirect
- 在
sendRedirect
的情况下,请求被转移到另一个资源,另一个域或不同的服务器以进行进一步处理。- 当您使用
sendRedirect
时,容器会将请求传输到客户端或浏览器,因此sendRedirect
方法中给出的URL作为对客户端的新请求可见。- 在
sendRedirect
调用的情况下,旧的请求和响应对象将丢失,因为它被浏览器视为新请求。- 在地址栏中,我们可以看到新的重定向地址。它不透明。
sendRedirect
速度较慢,因为需要额外的往返行程,因为会创建一个全新的请求并丢失旧的请求对象。需要两个浏览器请求。- 但是在
sendRedirect
中,如果我们想要使用,我们必须将数据存储在会话中或传递URL。哪一个好?
它取决于哪种方法更有用的场景。
如果你想控制转移到新的服务器或上下文,它被视为全新的任务,那么我们去
sendRedirect
。通常,如果在浏览器重新加载网页时可以安全地重复操作并且不会影响结果,则应使用转发。
Forward(ServletRequest request, ServletResponse response)
和sendRedirect(String url)
之间的区别仅在于
向前():
forward()
方法在服务器端执行。forward ()
方法由servlet容器提供。forward()
方法比sendRedirect()
方法快。RequestDispatcher
界面中声明。的sendRedirect():
在Web开发世界中,术语“重定向”是向客户端发送空HTTP响应的行为,其中仅包含客户端必须向其发送全新GET请求的新URL的Location
头。所以基本上:
some.jsp
发送HTTP请求。Location: other.jsp
标头发回HTTP响应other.jsp
发送HTTP请求(这反映在浏览器地址栏中!)other.jsp
。您可以使用Web浏览器的内置/插件开发人员工具集进行跟踪。在Chrome / IE9 / Firebug中按F12,然后选中“网络”部分进行查看。
恰好以上是由sendRedirect("other.jsp")
实现的。 RequestDispatcher#forward()
不发送重定向。相反,它使用目标页面的内容作为HTTP响应。
some.jsp
发送HTTP请求。other.jsp
。但是,由于原始HTTP请求是some.jsp
,浏览器地址栏中的URL保持不变。
RequestDispatcher
在MVC范例中非常有用,并且/或者当您想要隐藏JSP直接访问时。您可以将JSP放在/WEB-INF
文件夹中,并使用Servlet
来控制,预处理和后处理请求。 /WEB-INF
文件夹中的JSP不能通过URL直接访问,但Servlet
可以使用RequestDispatcher#forward()
访问它们。
例如,你可以在/WEB-INF/login.jsp
中有一个JSP文件,在LoginServlet
的url-pattern
上有一个/login
。当你调用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
pattern。
RequestDispatcher
接口允许您执行服务器端转发/包含,而sendRedirect()
执行客户端重定向。在客户端重定向中,服务器将发回HTTP状态代码302
(临时重定向),这导致Web浏览器针对重定向位置处的内容发出全新的HTTP GET
请求。相反,当使用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()
:通过使用它,我们可以转发或包含跨不同服务器的请求。在这种情况下,客户端在重定向页面时获得一个暗示,但在上述过程中,客户端将无法获得推断
Dispatcher允许请求数据从一个servlet传送到另一个servlet。请求调度程序的替代方案是发送重定向但是对于每个新请求发送重定向返回到网络上相反的请求调度程序发生在服务器内。
例
Servlet Dispatcher在Java中让我们通过简单的例子理解请求调度程序的概念。考虑我们有三个名为servlet1,servlet2和Servlet3的servlet的情况。如果我们不使用调度程序,每当我们请求servlet1时,服务器将控制传递给servlet1,之后如果我们请求servlet2,则控制从servlet 1返回到服务器并传递给servlet2。在这种情况下,如果服务器位于印度并且从美国请求servlet,那么对于第二个请求,它必须返回到服务器(印度)并返回到servlet(美国)。如果我们在请求和响应之间有大量流量,则此选项不好。这个问题的解决方案是调度员。
Java中的Servlet Dispatcher在同样的情况下,如果我们在服务器中使用调度程序,那么控制将从servlet1传递到servlet2,而不会返回到服务器而不涉及网络。这个概念也称为servlet链。它被称为servlet链接,因为我们正在创建servlet请求链,从servlet1到servlet2,Servlet2到Servlet3,服务器将从servlet3获取数据。
数据传递
在servlet链接中,不仅传递控制,而且数据也从一个servlet传递到另一个servlet,这与发送重定向相比是主要优点。在发送重定向中,每次获取新数据时,每个请求都是新请求。
考虑到servlet1有一些请求参数应该由servlet3执行,然后数据可以从servlet1传递到servlet2,然后从servlet2传递到servlet3,所以这里我们保留从一个servlet到其他servlet的请求。
请求的生命非常小,一旦我们得到响应,请求就结束了,但请求的生命可以从一个servlet保存到其他。借助于此,我们可以在许多servlet中划分任务。
坏处
大多数情况下,调度员都是高效的,但是如果数据量很大,或者我们根本不需要数据,或者如果是低流量,则可以有效地发送重定向工作。