天天看點

forward與redirect的差別

1.從位址欄顯示來說

forward是伺服器請求資源,伺服器直接通路目标位址的URL,把那個URL的響應内容讀取過來,然後把這些内容再發給浏覽器.浏覽器根本不知道伺服器發送的内容從哪裡來的,是以它的位址欄還是原來的位址.

redirect是服務端根據邏輯,發送一個狀态碼,告訴浏覽器重新去請求那個位址.是以位址欄顯示的是新的URL.

2.從資料共享來說

forward:轉發頁面和轉發到的頁面可以共享request裡面的資料.

redirect:不能共享資料.

3.從運用地方來說

forward:一般用于使用者登陸的時候,根據角色轉發到相應的子產品.

redirect:一般用于使用者登出登陸時傳回首頁面和跳轉到其它的網站等.

4.從效率來說

forward:高.

redirect:低.

本質差別

解釋一

一句話,轉發是伺服器行為,重定向是用戶端行為。為什麼這樣說呢,這就要看兩個動作的工作流程:

轉發過程:客戶浏覽器發送http請求----》web伺服器接受此請求--》調用内部的一個方法在容器内部完成請求處理和轉發動作----》将目标資源發送給客戶;在這裡,轉發的路徑必須是同一個web容器下的url,其不能轉向到其他的web路徑上去,中間傳遞的是自己的容器内的request。在客戶浏覽器路徑欄顯示的仍然是其第一次通路的路徑,也就是說客戶是感覺不到伺服器做了轉發的。轉發行為是浏覽器隻做了一次通路請求。

重定向過程:客戶浏覽器發送http請求----》web伺服器接受後發送302狀态碼響應及對應新的location給客戶浏覽器--》客戶浏覽器發現是302響應,則自動再發送一個新的http請求,請求url是新的location位址----》伺服器根據此請求尋找資源并發送給客戶。在這裡 location可以重定向到任意URL,既然是浏覽器重新發出了請求,則就沒有什麼request傳遞的概念了。在客戶浏覽器路徑欄顯示的是其重定向的路徑,客戶可以觀察到位址的變化的。重定向行為是浏覽器做了至少兩次的通路請求的。

解釋二

重定向,其實是兩次request,

第一次,用戶端request A,伺服器響應,并response回來,告訴浏覽器,你應該去B。這個時候IE可以看到位址變了,而且曆史的回退按鈕也亮了。重定向可以通路自己web應用以外的資源。在重定向的過程中,傳輸的資訊會被丢失。

例子:

請求轉發是伺服器内部把對一個request/response的處理權,移交給另外一個

對于用戶端而言,它隻知道自己最早請求的那個A,而不知道中間的B,甚至C、D。 傳輸的資訊不會丢失。

例子:

解釋三

假設你去辦理某個執照,

重定向:你先去了A局,A局的人說:“這個事情不歸我們管,去B局”,然後,你就從A退了出來,自己乘車去了B局。

轉發:你先去了A局,A局看了以後,知道這個事情其實應該B局來管,但是他沒有把你退回來,而是讓你坐一會兒,自己到後面辦公室聯系了B的人,讓他們辦好後,送了過來。

三、請求重定向與請求轉發的比較

盡管HttpServletResponse.sendRedirect方法和RequestDispatcher.forward方法都可以讓浏覽器獲得另外一個URL所指向的資源,但兩者的内部運作機制有着很大的差別。下面是HttpServletResponse.sendRedirect方法實作的請求重定向與RequestDispatcher.forward方法實作的請求轉發的總結比較:

(1)RequestDispatcher.forward方法隻能将請求轉發給同一個WEB應用中的元件;而 HttpServletResponse.sendRedirect 方法不僅可以重定向到目前應用程式中的其他資源,還可以重定向到同一個站點上的其他應用程式中的資源,甚至是使用絕對URL重定向到其他站點的資源。如果傳遞給HttpServletResponse.sendRedirect 方法的相對URL以“/”開頭,它是相對于整個WEB站點的根目錄;如果建立RequestDispatcher對象時指定的相對URL以“/”開頭,它是相對于目前WEB應用程式的根目錄。

(2)調用HttpServletResponse.sendRedirect方法重定向的通路過程結束後,浏覽器位址欄中顯示的URL會發生改變,由初始的URL位址變成重定向的目标URL;而調用RequestDispatcher.forward 方法的請求轉發過程結束後,浏覽器位址欄保持初始的URL位址不變。

(3)HttpServletResponse.sendRedirect方法對浏覽器的請求直接作出響應,響應的結果就是告訴浏覽器去重新發出對另外一個URL的 通路請求,這個過程好比有個綽号叫“浏覽器”的人寫信找張三借錢,張三回信說沒有錢,讓“浏覽器”去找李四借,并将李四現在的通信位址告訴給了“浏覽器”。于是,“浏覽器”又按張三提供通信位址給李四寫信借錢,李四收到信後就把錢彙給了“浏覽器”。可見,“浏覽器”一共發出了兩封信和收到了兩次回複, “浏覽器”也知道他借到的錢出自李四之手。RequestDispatcher.forward方 法在伺服器端内部将請求轉發給另外一個資源,浏覽器隻知道發出了請求并得到了響應結果,并不知道在伺服器程式内部發生了轉發行為。這個過程好比綽号叫“浏覽器”的人寫信找張三借錢,張三沒有錢,于是張三找李四借了一些錢,甚至還可以加上自己的一些錢,然後再将這些錢彙給了“浏覽器”。可見,“浏覽器”隻發 出了一封信和收到了一次回複,他隻知道從張三那裡借到了錢,并不知道有一部分錢出自李四之手。

(4)RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬于同一個通路請求和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的request對象和 response對象,它們屬于兩個獨立的通路請求和響應過程。對于同一個WEB應用程式的内部資源之間的跳轉,特别是跳轉之前要對請求進行一些前期預處理,并要使用HttpServletRequest.setAttribute方法傳遞預處理結果,那就應該使用 RequestDispatcher.forward方法。不同WEB應用程式之間的重定向,特别是要重定向到另外一個WEB站點上的資源的情況,都應該使用HttpServletResponse.sendRedirect方法。

(5)無論是RequestDispatcher.forward方法,還是HttpServletResponse.sendRedirect方法,在調用它們之前,都不能有内容已經被實際輸出到了用戶端。如果緩沖區中已經有了一些内容,這些内容将被從緩沖區中清除。

zend framework 中的應用

控制這種分發過程的動作控制器方法是_forward() ;在任意的pre/postDispatch() 或者動作中調用該方法,并傳入動作、控制器、子產品、以及可選的附加參數,就可以進入新的動作。

三種請求轉發得方式

  1. public function fooAction() {
  2. // forward to another action in the current controller and module:
  3. $this->_forward('bar', null, null, array('baz' => 'bogus'));
  4. }
  5. public function barAction() {
  6. // forward to an action in another controller:
  7. // FooController::bazAction(),
  8. // in the current module:
  9. $this->_forward('baz', 'foo', null, array('baz' => 'bogus'));
  10. }
  11. public function bazAction() {
  12. // forward to an action in another controller in another module,
  13. // Foo_BarController::bazAction():
  14. $this->_forward('baz', 'bar', 'foo', array('baz' => 'bogus'));
  15. }

頁面跳轉得方法是

$this->_redirect('/login/add');

什麼時候用forward什麼時候用redirect呢???

forward是轉發,redirect是重定向 具體用什麼歸結到就一個問題,要不要資料共享(共享request、response對象) 當你在一個servlet中做一件事,但事情還沒有做完卻要跳到另一個組建(可以是jsp、servlet等),就用轉發; 當你在一個servlet中做一件事,已經做完了後要跳到另一個組建,可以用重定向

重定向是伺服器讓用戶端(浏覽器)重新發送一個定向請求(貌似就是直接改變浏覽器位址欄位址),轉發是在伺服器内轉到另一個組建(但還是原來的請求),位址欄不會改變

轉載于:https://www.cnblogs.com/heartstage/p/3389727.html