Forward和Redirect代表了兩種請求轉(zhuǎn)發(fā)方式:直接轉(zhuǎn)發(fā)和間接轉(zhuǎn)發(fā)鞋仍。直接轉(zhuǎn)發(fā)就是由控制器來控制請求應(yīng)該轉(zhuǎn)發(fā)給那個信息資源据某。然后由這些信息資源處理請求粱腻,處理完以后還可能轉(zhuǎn)發(fā)給另外的信息資源來返回給用戶商膊,這個過程就是經(jīng)典的MVC模式宾濒;而間接轉(zhuǎn)發(fā)有時也叫做重定向军援,它一般用于避免用戶的非正常訪問仅淑。區(qū)別在于:
1.從地址欄顯示來說
forward是服務(wù)器請求資源,服務(wù)器直接訪問目標地址的URL,把那個URL的響應(yīng)內(nèi)容讀取過來,然后把這些內(nèi)容再發(fā)給瀏覽器胸哥。瀏覽器根本不知道服務(wù)器發(fā)送的內(nèi)容從哪里來的涯竟,所以它的地址欄還是原來的地址。
redirect是服務(wù)端根據(jù)邏輯,發(fā)送一個狀態(tài)碼庐船,告訴瀏覽器重新去請求那個地址银酬。所以地址欄顯示的是新的URL。
2.從數(shù)據(jù)共享來說
forward:轉(zhuǎn)發(fā)頁面和轉(zhuǎn)發(fā)到的頁面可以共享request里面的數(shù)據(jù)筐钟。
redirect:不能共享數(shù)據(jù)揩瞪。
3.從運用地方來說
forward:一般用于用戶登陸的時候,根據(jù)角色轉(zhuǎn)發(fā)到相應(yīng)的模塊。
redirect:一般用于用戶注銷登陸時返回主頁面和跳轉(zhuǎn)到其它的網(wǎng)站等篓冲。
4.從效率來說
forward:高李破。
redirect:低。
關(guān)于兩者的本質(zhì)區(qū)別壹将,有以下幾種解釋:
解釋一
一句話嗤攻,轉(zhuǎn)發(fā)是服務(wù)器行為,重定向是客戶端行為诽俯。為什么這樣說呢妇菱,這就要看兩個動作的工作流程:
轉(zhuǎn)發(fā)過程:客戶瀏覽器發(fā)送http請求——web服務(wù)器接受此請求——調(diào)用內(nèi)部的一個方法在容器內(nèi)部完成請求處理和轉(zhuǎn)發(fā)動作——將目標資源。發(fā)送給客戶暴区;在這里闯团,轉(zhuǎn)發(fā)的路徑必須是同一個web容器下的url,其不能轉(zhuǎn)向到其他的web路徑上去仙粱,中間傳遞的是自己的容器內(nèi)的request偷俭。在客 戶瀏覽器路徑欄顯示的仍然是其第一次訪問的路徑,也就是說客戶是感覺不到服務(wù)器做了轉(zhuǎn)發(fā)的缰盏。轉(zhuǎn)發(fā)行為是瀏覽器只做了一次訪問請求。
重定向過程:客戶瀏覽器發(fā)送http請求——web服務(wù)器接受后發(fā)送302狀態(tài)碼響應(yīng)及對應(yīng)新的location給客戶瀏覽器——客戶瀏覽器發(fā)現(xiàn) 是302響應(yīng)淹遵,則自動再發(fā)送一個新的http請求口猜,請求url是新的location地址——服務(wù)器根據(jù)此請求尋找資源并發(fā)送給客戶。在這里 location可以重定向到任意URL透揣,既然是瀏覽器重新發(fā)出了請求济炎,則就沒有什么request傳遞的概念了。在客戶瀏覽器路徑欄顯示的是其重定向的 路徑辐真,客戶可以觀察到地址的變化的须尚。重定向行為是瀏覽器做了至少兩次的訪問請求的。
解釋二
重定向侍咱,其實是兩次request:第一次耐床,客戶端request A,服務(wù)器響應(yīng),并response回來楔脯,告訴瀏覽器撩轰,你應(yīng)該去B。這個時候IE可以看到地址變了,而且歷史的回退按鈕也亮了堪嫂。重定向可以訪問自己web應(yīng)用以外的資源偎箫。在重定向的過程中,傳輸?shù)男畔粊G失皆串。
例子:
請求轉(zhuǎn)發(fā)是服務(wù)器內(nèi)部把對一個request/response的處理權(quán)淹办,移交給另外一個,對于客戶端而言恶复,它只知道自己最早請求的那個A怜森,而不知道中間的B,甚至C寂玲、D塔插。 傳輸?shù)男畔⒉粫G失。
解釋三
假設(shè)你去辦理某個執(zhí)照拓哟, 重定向:你先去了A局想许,A局的人說:“這個事情不歸我們管,去B局”断序,然后流纹,你就從A退了出來,自己乘車去了B局违诗。 轉(zhuǎn)發(fā):你先去了A局漱凝,A局看了以后,知道這個事情其實應(yīng)該B局來管诸迟,但是他沒有把你退回來茸炒,而是讓你坐一會兒,自己到后面辦公室聯(lián)系了B的人阵苇,讓他們辦好后壁公,送了過來。
請求重定向與請求轉(zhuǎn)發(fā)的比較:
盡管HttpServletResponse.sendRedirect方法和RequestDispatcher.forward方法都可以讓瀏覽器獲 得另外一個URL所指向的資源绅项,但兩者的內(nèi)部運行機制有著很大的區(qū)別紊册。下面是HttpServletResponse.sendRedirect方法實現(xiàn) 的請求重定向與RequestDispatcher.forward方法實現(xiàn)的請求轉(zhuǎn)發(fā)的總結(jié)比較:
(1)RequestDispatcher.forward方法只能將請求轉(zhuǎn)發(fā)給同一個WEB應(yīng)用中的組件;而 HttpServletResponse.sendRedirect 方法不僅可以重定向到當前應(yīng)用程序中的其他資源快耿,還可以重定向到同一個站點上的其他應(yīng)用程序中的資源囊陡,甚至是使用絕對URL重定向到其他站點的資源。如果傳遞給HttpServletResponse.sendRedirect 方法的相對URL以“/”開頭掀亥,它是相對于整個WEB站點的根目錄撞反;如果創(chuàng)建RequestDispatcher對象時指定的相對URL以“/”開頭,它 是相對于當前WEB應(yīng)用程序的根目錄搪花。
(2)調(diào)用HttpServletResponse.sendRedirect方法重定向的訪問過程結(jié)束后痢畜,瀏覽器地址欄中顯示的URL會發(fā)生改變垛膝,由初 始的URL地址變成重定向的目標URL;而調(diào)用RequestDispatcher.forward 方法的請求轉(zhuǎn)發(fā)過程結(jié)束后丁稀,瀏覽器地址欄保持初始的URL地址不變吼拥。
(3)HttpServletResponse.sendRedirect方法對瀏覽器的請求直接作出響應(yīng),響應(yīng)的結(jié)果就是告訴瀏覽器去重新發(fā)出對另外一 個URL的 訪問請求线衫,這個過程好比有個綽號叫“瀏覽器”的人寫信找張三借錢凿可,張三回信說沒有錢,讓“瀏覽器”去找李四借授账,并將李四現(xiàn)在的通信地址告訴給了“瀏覽 器”枯跑。于是,“瀏覽器”又按張三提供通信地址給李四寫信借錢白热,李四收到信后就把錢匯給了“瀏覽器”敛助。可見屋确,“瀏覽器”一共發(fā)出了兩封信和收到了兩次回復纳击, “瀏覽器”也知道他借到的錢出自李四之手。RequestDispatcher.forward方 法在服務(wù)器端內(nèi)部將請求轉(zhuǎn)發(fā)給另外一個資源攻臀,瀏覽器只知道發(fā)出了請求并得到了響應(yīng)結(jié)果焕数,并不知道在服務(wù)器程序內(nèi)部發(fā)生了轉(zhuǎn)發(fā)行為。這個過程好比綽號叫“瀏 覽器”的人寫信找張三借錢刨啸,張三沒有錢堡赔,于是張三找李四借了一些錢,甚至還可以加上自己的一些錢设联,然后再將這些錢匯給了“瀏覽器”善已。可見离例,“瀏覽器”只發(fā) 出了一封信和收到了一次回復换团,他只知道從張三那里借到了錢,并不知道有一部分錢出自李四之手粘招。
(4)RequestDispatcher.forward方法的調(diào)用者與被調(diào)用者之間共享相同的request對象和response對象,它們屬于同 一個訪問請求和響應(yīng)過程偎球;而HttpServletResponse.sendRedirect方法調(diào)用者與被調(diào)用者使用各自的request對象和 response對象洒扎,它們屬于兩個獨立的訪問請求和響應(yīng)過程。對于同一個WEB應(yīng)用程序的內(nèi)部資源之間的跳轉(zhuǎn)衰絮,特別是跳轉(zhuǎn)之前要對請求進行一些前期預處 理袍冷,并要使用HttpServletRequest.setAttribute方法傳遞預處理結(jié)果,那就應(yīng)該使用 RequestDispatcher.forward方法猫牡。不同WEB應(yīng)用程序之間的重定向胡诗,特別是要重定向到另外一個WEB站點上的資源的情況,都應(yīng)該 使用HttpServletResponse.sendRedirect方法。
(5)無論是RequestDispatcher.forward方法煌恢,還是HttpServletResponse.sendRedirect方法骇陈,在調(diào)用它們之前,都不能有內(nèi)容已經(jīng)被實際輸出到了客戶端瑰抵。如果緩沖區(qū)中已經(jīng)有了一些內(nèi)容你雌,這些內(nèi)容將被從緩沖區(qū)中清除。