forward()sendRedirect()之间的概念区别是什么?

#1 楼


requestDispatcher-forward()方法


当我们使用forward方法时,请求被转移到同一服务器内的另一个资源以进行进一步处理。在forward的情况下,Web容器在内部处理所有处理,并且不涉及客户端或浏览器。
当在forward对象上调用requestDispatcher时,我们传递了请求和响应对象,因此旧请求对象存在于
从视觉上看,我们看不到转发的地址,它是透明的。
使用forward()方法比sendRedirect更快。
当我们重定向时使用转发,并且我们想在新资源中使用相同的数据,可以使用request.setAttribute(),因为我们有一个可用的请求对象。

SendRedirect

sendRedirect的情况下,请求已转移到另一个资源,另一个域或另一个
服务器r进一步处理。
当使用sendRedirect时,容器会将请求传输到客户端或浏览器,因此sendRedirect方法内部给出的URL作为对客户端的新请求可见。
如果使用sendRedirect调用时,旧的请求和响应对象将丢失,因为浏览器将其视为新请求。
在地址栏中,我们能够看到新的重定向地址。它不是透明的。
sendRedirect较慢,因为需要一个额外的往返行程,因为创建了一个全新的请求并且旧的请求对象丢失了。需要两个浏览器请求。
但是在sendRedirect中,如果要为新资源使用相同的数据,则必须将数据存储在会话中或与URL一起传递。

一个好吗?

这取决于哪种方法更有用的情况。

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




#2 楼

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

客户端向some.jsp发送HTTP请求。
服务器向Location: other.jsp标头发送HTTP响应
客户端向other.jsp发送HTTP请求(此信息反映在浏览器地址中bar!)
服务器发送回HTTP响应,内容为other.jsp

您可以使用Web浏览器的内置/附加开发人员工具集对其进行跟踪。在Chrome / IE9 / Firebug中按F12并检查“网络”部分以查看它。
以上正是通过sendRedirect("other.jsp")实现的。 RequestDispatcher#forward()不发送重定向。而是将目标页面的内容用作HTTP响应。

客户端将HTTP请求发送到some.jsp
服务器将HTTP响应发送回内容为other.jsp

但是,由于原始HTTP请求是some.jsp,因此浏览器地址栏中的URL保持不变。同样,在some.jsp后面的控制器中设置的任何请求属性都将在other.jsp中可用。在重定向期间不会发生这种情况,因为您基本上是在强迫客户端在other.jsp上创建一个新的HTTP请求,从而丢弃some.jsp上的原始请求,包括其所有属性。在MVC范例中和/或要从直接访问中隐藏JSP时很有用。您可以将JSP放在RequestDispatcher文件夹中,并使用/WEB-INF来控制,预处理和后处理请求。 URL不能直接访问Servlet文件夹中的JSP,但是/WEB-INF可以使用Servlet来访问它们。
例如,您可以在RequestDispatcher#forward()中有一​​个JSP文件,而在/WEB-INF/login.jspLoginServlet上有一个url-pattern。调用/login时,将调用servlet的http://example.com/context/login。您可以在其中进行任何预处理,最后转发请求,例如:
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);

提交表单时,通常要使用doGet()
 POST 

这样,将调用servlet的<form action="login" method="post"> ,您可以在其中进行任何后处理操作(例如,验证,业务逻辑,登录用户等)。是任何错误,那么您通常希望将请求转发回同一页面,并在输入字段旁边显示错误,依此类推。您可以为此使用doPost()
如果RequestDispatcher成功,则通常要重定向请求,以便在用户刷新请求(例如,按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上发出新的POST请求。然后刷新请求将仅刷新重定向的请求,而不刷新初始请求。这将避免“两次提交”,混乱和不良的用户体验。这也称为GET模式。
另请参见:

servlet如何工作?实例化,会话,共享变量和多线程处理
如何在Servlet中执行doGet和doPost
如何在JSP中执行验证并以相同形式显示错误消息?
HttpServletResponse sendRedirect永久性


评论


当我从servlet重定向到jsp页面时,jsp页面被部分加载,如stackoverflow.com/questions/12337624/…中所示。我希望在有人点击foo.com时运行的第一件事就是该servlet。从Servlet,我对网站的index.jsp页面执行response.sendRedirect(“ ..”)。但这会错过jsp页面中的css文件和一些文本,从而导致页面的部分加载。但是,当我将网站的欢迎页面设置为index.jsp时,一切正常,页面加载完成。重定向有什么问题?

– saplingPro
2012年9月9日上午11:16

#3 楼

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

评论


后者实际上是向前的,而不是重定向。

–阿黛尔·安萨里(Adeel Ansari)
2010年1月12日,下午6:40

#4 楼


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




评论


一张图片胜过千言万语 :)

– Eugen Labun
18年11月26日在23:30

#5 楼

根据您要执行的操作,这两种方法中的任何一种都可能是“更好”的,即更合适。浏览器往返。但是浏览器中看到的URL仍然是原始地址,因此您在此处创建了一些不一致的地方。 ,或更改协议(例如,从HTTP更改为HTTPS),或同时更改两者。并且浏览器知道新的URL。但是,这需要在服务器和客户端之间进行额外的往返操作。

评论


网路上的这个区隔并未在网路上提及得足够多:「或变更通讯协定(例如从HTTP变更为HTTPS),或同时变更两者」

– Perdomoff
16年1月14日在22:32

#6 楼

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

RquestDispatcher用于在我认为的服务器中搜索内容。它是服务器端进程,与SendRedirect()方法相比,速度更快。但事实是,它不会使浏览器在所需的日期或内容所在的服务器上相互联系,也不会要求浏览器更改“ URL”选项卡中的URL。因此给用户带来的不便。

#7 楼

从技术上讲,如果我们需要将控制权转移到其他域或实现任务分离,则应该使用重定向。例如,在付款应用程序中,我们首先执行PaymentProcess,然后重定向到displayPaymentInfo 。如果客户端刷新浏览器,则仅displayPaymentInfo会再次执行,并且PaymentProcess将不会重复。但是,如果在这种情况下使用转发,则PaymentProcess和displayPaymentInfo都将顺序执行,这可能会导致数据混乱。 sendRedirect

#8 楼

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


request.forward(req,res):此方法用于将请求从一个Web资源转发到另一资源。即从一个Servlet到另一个Servlet或从一个Web应用程序到另一个Web应用程序。我们可以将请求或响应转发或包含在同一服务器中。

response.include(req,res):通过使用它,我们可以跨不同服务器转发或包括请求或响应。在这种情况下,客户端在重定向页面时会得到提示,但是在上述过程中,客户端将不会得到提示。

#9 楼

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

forward():


forward()方法在服务器端执行。同一服务器内的其他资源。
由于servlet容器提供了forward ()方法,因此它不依赖于客户端的请求协议。
请求由目标资源共享。
只有一个调用
可以在服务器中使用。
我们看不到转发的消息,它是透明的。
forward()方法比sendRedirect()方法快。
RequestDispatcher接口中声明。

sendRedirect():


sendRedirect()方法在客户端执行。
请求被传输到其他资源到不同的服务器。
HTTP下提供了sendRedirect()方法,因此只能与HTTP客户端一起使用。
将为目标资源创建新请求。
将消耗两个请求和响应调用。 />它可以在服务器内外使用。
我们可以看到重定向的地址,它不是透明的。
在HttpServletResponse中声明。