A.1、Redirect和Forward的区别
web开发开发中进行页面跳转的方法有两个,forward和redirect。
Forward
Forward简单来说就是在服务器端完成叶面跳转,服务端从A页forward到B页,对于客户端来说一直都在访问A页,不知道有个B页存在(客户端地址栏看不到B页地址,它一直显示A页的地址)。
Forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器。浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址。
Forward是在web应用程序之内进行的,可以访问web应用程序所设定的内部目录,像是WEB-INF目录,只能在Web应用程序中进行,不能指定至其它的Web应用程序的地址。
Forward跳转的页面中,request作用域的变量都能生效,因为无论forward多少次,都是同一个request。
Redirect
Redirect就容易理解的多了,从A页forward到B页,服务端告诉客户端,你要从A跳到B,由客户端发出指挥,所以客户端地址栏看到从A页变成B页了。
Redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址。所以地址栏显示的是新的URL。
Redirect的请求由浏览器发出,所以不能访问Web应用程序中的隐藏目录,像是WEB-INF,重新是由浏览器重新要求一个网页,可以指定至其他的Web应用程序地址。
Reirect是由客户端指挥的,所以redirect以后就已经是第二次request了。
A.2、forward方法和include的区别
Forward
forward方法调用后在响应中的没有提交的内容被自动消除。将请求转发给其他的Servlet后,由被调用的Servlet负责对请求做出响应,而原先Servlet的执行则终止
Include
include方法使原先的Servlet和转发到的Servlet都可以输出响应信息,即原先的Servlet还可以继续输出响应信息。
A.3、三者区别
三个都可以对用户的request进行转发,但是还是有许多的不同,差别最主要集中在如下几个方面:
1、forward与include共享Request范围内的对象,而redirect则不行,即:如果一个javabean被声明为request范围的话,则被forward到的资源也可以访问这个javabean,而redriect则不行。
2、forward与include基本上都是转发到context内部的资源,而redirect可以重定向到外部的资源,如:req.sendRedriect(http://www.mocuai.com);
3、RequestDispatcher.forward()仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址,他是不会改变Request的值,如果你需要在下一个页面中能从中获取新的信息的话,你可以Request.setAttribute()来放置一些标志,这样从下一个页面中获取;HttpServletResponse.sendRedirect()方法则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用RequestDispatcher.forward()方法,并且,这样也有助于隐藏实际的链接。
B、Redirect和Forward、Include的应用
B.1、在JAVA中应用
B.1.1、Forward和Include
forward、include由javax.servlet.RequestDispatcher来封装的,其中声明如下:
void forward(ServletRequest req,ServletResponse res)
void include(ServeltRequest req,ServletResponse res)
可以通过两种方式得到RequestDispatcher:
ServletContext.getRequestDispatcher(String path);
其中这里的path必须开始为"/",即这里的path必须相对于context的root.
ServeltRequest.getRequestDispatcher(String path)
这里的path可以为相对路径,如果path开始为"/",则也认为是从context的root开始的。
B.1.2、Redirect
Redirect由HttpServletResponse.sendRedirect(String location)来支持
B.2、在Spring中应用
B.2.1、Forward和Include
在Spring mvc框架中一个控制器通常返回一个视图名,然后视图解析器把它解析到某种视图技术上实现。对于使用JSP/Servlet视图技术时,其实就是使用RequestDispatcher.forward()或RequestDispatcher.include()方法。比如当客户在浏览器中输入一个URL(如:http://xxx/1.html),视图解析器把它解析到一个jsp资源上,显示给客户的是jsp资源的数据,而客户浏览器中的地址没有变化。
比如有些时候我们处理表单提交时,若使用Spring内部forward机制,一个控制器将接收请求并进行处理,处理完成后它可能返回一个视图名,这时这个视图就会有一个问题就是返回的视图会得到之前POST的数据,这容易造成混淆。还有一个问题是若用户刷新页面会导致数据重复提交。若使用Redirect机制,返回的视图是GET等到的,是不同的请求,故可以避免多次提交的问题。
forward: 前缀
使用UrlBasedViewResolver的redirect:前缀。
B.2.2、Redirect
方法一:RedirectView
Spring中Redirect实现方法之一是让控制器(Controller)创建和返回一个RedirectView,这种情况下,DispatcherServlet不会使用通常的视图解析机制,而是让控制器指定的RedirectView视图来处理表单提交后的工作。
RedirectView会调用HttpServletResponse.sendRedirect(),其中的model值将被转化为String传递给redirect的视图。
方法二:redirect:前缀
第二种方法是使用UrlBasedViewResolver的redirect:前缀。
从设计理念上来讲第二种方法比较合理,它减少了耦合。