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:前綴。
從設計理念上來講第二種方法比較合理,它減少了耦合。