1、 定義
-
Forward(請(qǐng)求轉(zhuǎn)向)
:服務(wù)器程序內(nèi)部請(qǐng)求轉(zhuǎn)向,這個(gè)特性允許前一個(gè)程序用于處理請(qǐng)求,而后一個(gè)程序用來(lái)返回響應(yīng)。 -
Redirect(重定向)
:服務(wù)端發(fā)送給客戶端一個(gè)重定向的臨時(shí)響應(yīng)頭,這個(gè)響應(yīng)頭包含重定向之后的URL,客戶端用新的URL重新向服務(wù)器發(fā)送一個(gè)新的請(qǐng)求。
2、定義簡(jiǎn)單理解
- 請(qǐng)求轉(zhuǎn)發(fā)只是把請(qǐng)求轉(zhuǎn)發(fā)給服務(wù)器上(通常是同一個(gè)Web應(yīng)用中)的另一個(gè)組件(Servlet或Jsp等)。
- 重定向則只是告訴客戶(瀏覽器)去訪問(wèn)另一個(gè)URL(可能是同一個(gè)Web站點(diǎn)甚至其他站點(diǎn))。
3、本質(zhì)區(qū)別
- 請(qǐng)求轉(zhuǎn)發(fā)發(fā)生在服務(wù)器端,由服務(wù)器(比如servlet)控制。
- 重定向發(fā)生在客戶端,由客戶(通常是瀏覽器)控制。
4、請(qǐng)求和響應(yīng)次數(shù)
- 請(qǐng)求轉(zhuǎn)發(fā)過(guò)程在同一個(gè)請(qǐng)求當(dāng)中完成,只會(huì)返回一個(gè)響應(yīng)。
- 重定向過(guò)程則發(fā)生在兩個(gè)不同的請(qǐng)求中,會(huì)返回兩個(gè)不同響應(yīng)。
5、基于第4點(diǎn),進(jìn)一步分析
- 請(qǐng)求轉(zhuǎn)發(fā)后可以在服務(wù)器端獲取本次請(qǐng)求對(duì)象上保存的信息(比如在Servlet中將用戶名保存到當(dāng)前request對(duì)象中,轉(zhuǎn)發(fā)給另一組件(如JSP)后,另一組件可以通過(guò)request對(duì)象取得用戶名信息)。
- 請(qǐng)求轉(zhuǎn)發(fā)后,瀏覽器地址欄URL不會(huì)發(fā)生改變。
- 重定向后則無(wú)法在服務(wù)器端獲取第一次請(qǐng)求對(duì)象上保存的信息(比如還是在Servlet中將用戶名保存到當(dāng)前request對(duì)象中,并重定向到一個(gè)新的URL,然后在新URL指向的地址中(比如還是某個(gè)Servlet)就無(wú)法獲取原先保存在第一個(gè)請(qǐng)求中的信息。很明顯,用戶名是保存在第一次請(qǐng)求的對(duì)象中,但并沒(méi)有保存在本次(第二次)請(qǐng)求的對(duì)象中)。
- 重定向后,瀏覽器地址欄URL變?yōu)樾碌腢RL(因?yàn)闉g覽器確實(shí)給新的URL發(fā)送了一個(gè)新的請(qǐng)求)。
6、服務(wù)器端調(diào)用的方法
- 請(qǐng)求轉(zhuǎn)發(fā)使用RequestDispatcher對(duì)象的forward()或include()方法(他們的區(qū)別可參考:Servlet中請(qǐng)求轉(zhuǎn)發(fā)時(shí)forword()和include()的區(qū)別)。
- 重定向則使用HttpServletResponse對(duì)象的sendRedirect()方法。
7、基于第6點(diǎn),進(jìn)一步分析
- RequestDispatcher對(duì)象是通過(guò)調(diào)用HttpServletRequest對(duì)象的getRequestDispatcher()方法得到的,所以forward()或include()本質(zhì)來(lái)說(shuō)是屬于請(qǐng)求對(duì)象的方法,所以請(qǐng)求轉(zhuǎn)發(fā)始終發(fā)生在一個(gè)請(qǐng)求當(dāng)中。
- sendRedirect()方法HttpServletResponse對(duì)象的方法,即響應(yīng)對(duì)象的方法。既然調(diào)用了響應(yīng)對(duì)象的方法,就表示本次請(qǐng)求過(guò)程已經(jīng)結(jié)束了,服務(wù)器即將向客戶端返回本次請(qǐng)求的響應(yīng)了。事實(shí)上,服務(wù)器確實(shí)返回了一個(gè)狀態(tài)碼為“302”,首部“Location”值為新的URL的響應(yīng)。然后瀏覽器就會(huì)根據(jù)“Location”首部指定的URL,重新發(fā)起一次新的請(qǐng)求,轉(zhuǎn)向這個(gè)目標(biāo)頁(yè)面,所以重定向?qū)嶋H上發(fā)生在兩個(gè)不同的請(qǐng)求當(dāng)中。
8、sendRedirect()和forword()中使用相對(duì)URL分析(站點(diǎn)為:http://localhost:8080/
,Web應(yīng)用為MyApp)。
- sendRedirect(URL):如果使用”/”開頭,則表示相對(duì)于整個(gè)Web站點(diǎn)的根目錄,如使用
sendRedirect(“/foo/myHtml.html”)
時(shí),容器建立的完整URL為:http://localhost:8080/foo/myHtml.html
。否則,就表示相對(duì)于當(dāng)前目錄。 -
request.getRequestDispatcher(URL).forward(req,res)
:如果使用”/”開頭,則表示相對(duì)于當(dāng)前Web應(yīng)用的根目錄,而非整個(gè)Web站點(diǎn)的根目錄,如使用request.getRequestDispatcher(/foo/myHtml.html).forward(req,res)
時(shí),容器會(huì)建立絕對(duì)(完整)的URL為:http://localhost:8080/MyApp/foo/myHtml.html
。否則,同樣表示相對(duì)于當(dāng)前目錄。
9、跳轉(zhuǎn)時(shí)機(jī)(有待考究)
- 請(qǐng)求轉(zhuǎn)發(fā)執(zhí)行到跳轉(zhuǎn)語(yǔ)句后馬上無(wú)條件跳轉(zhuǎn),之后的代碼不再執(zhí)行。
- 重定向則會(huì)在所有代碼執(zhí)行完畢后跳轉(zhuǎn),但不能再向response中寫入任何數(shù)據(jù)。(可以在重定向跳轉(zhuǎn)后加上return語(yǔ)句,實(shí)現(xiàn)馬上跳轉(zhuǎn))
10、執(zhí)行時(shí)機(jī)(相同點(diǎn))
- 請(qǐng)求轉(zhuǎn)發(fā)和重定向方法都必須在響應(yīng)提交(刷新響應(yīng)正文輸出到流中)之前執(zhí)行,否則會(huì)拋出IllegalStateException異常。
- 在轉(zhuǎn)發(fā)或重定向之前,響應(yīng)緩沖區(qū)中未提交的數(shù)據(jù)會(huì)被自動(dòng)清除。
11、響應(yīng)速度(理論上)
- 請(qǐng)求轉(zhuǎn)發(fā)相對(duì)快:因?yàn)檎?qǐng)求轉(zhuǎn)發(fā)過(guò)程在同一請(qǐng)求中。
- 重定向相對(duì)慢:因?yàn)橹囟ㄏ蜻^(guò)程發(fā)生在兩個(gè)不同的請(qǐng)求中。