Servlet學習筆記(四)之請求轉發與重定向(RequestDispatcher與sendRedirect)
ServletContext可以實現請求轉發(ServletContext請求轉發相關內容見之前部落格:http://blog.csdn.net/megustas_jjc/article/details/53191657),request也可以。HttpServletRequest 和 ServletContext 類似都是資料域物件 , 以Map方式保持資料。但是兩者也存在著區別:兩者的存活時間不同
- ServletContext物件 伺服器啟動物件建立,伺服器停止物件銷燬
- ServletRequest物件 當產生一次請求時建立,當響應結束後,物件銷燬
Request物件實現請求轉發
request物件實現請求轉發(轉發其實就是傳遞物件
應用:Servlet進行資料處理 — 生成結果 — 轉發結果給JSP顯示
通過request轉發請求,request儲存資料進行Servlet之間傳遞 ,以下是一個例子,利用request轉發請求,sat語法進行資料的傳遞,我們定義兩個Servlet類,分別為AServlet與BServlet:
Servlet路徑對映配置
AServlet:
BServlet
1.request物件提供了一個getRequestDispatcher方法,該方法返回一個RequestDispatcher物件,呼叫這個物件的forward方法可以實現請求轉發。
2.request物件同時也是一個域物件,開發人員通過request物件在實現轉發時,把資料通過request物件帶給其它web資源處理。(request擁有這些方法:setAttribute方法 getAttribute方法 removeAttribute方法 getAttributeNames方法)
RequestDispatcher物件
RequestDispatcher是一個Web資源的包裝器,可以用來把當前request傳遞到該資源,或者把新的資源包括到當前響應中,對於RequestDispatcher物件的常用使用如下:
RequestDispatcher物件從客戶端獲取請求request,並把它們傳遞給伺服器上的servlet,html或jsp。它有兩個方法:
- 用來傳遞request的,可以一個Servlet接收request請求,另一個Servlet用這個request請求來產生response。request傳遞的請求,response是客戶端返回的資訊。forward要在response到達客戶端之前呼叫,也就是 before response body output has been flushed。如果不是的話,它會報出異常。
- 用來記錄保留request和response,以後不能再修改response裡表示狀態的資訊。
Response的重定向例子與詳細介紹,可以參考之前的一篇關於ServletResponse的部落格:http://blog.csdn.net/megustas_jjc/article/details/53286372
其中需要注意的是RequestDispatcher與sendRedirect的區別
- request.getRequestDispatcher()是請求轉發,前後頁面共享一個request,因為共用一個request 物件,新航道英語forward()方法在伺服器端執行,因此可以保證資訊的共享。response.sendRedirect()是重新定向,前後頁面不是一個request。
- RequestDispatcher.forward()是在伺服器端執行; HttpServletResponse.sendRedirect()是通過向客戶瀏覽器傳送命令來完成.
所以RequestDispatcher.forward()對於瀏覽器來說是“透明的”;
而HttpServletResponse.sendRedirect()則不是。 - ServletContext.getRequestDispatcher(String url)中的url只能使用絕對路徑; 而
ServletRequest.getRequestDispatcher(String url)中的url可以使用相對路徑。因為
ServletRequest具有相對路徑的概念;而ServletContext物件無次概念。 - response.sendRedirect(url)跳轉到指定的URL地址,產生一個新的request,所以要傳遞引數只有在url後加參 數,如: url?id=1.
-
request.getRequestDispatcher(url).forward(request,response)是直接將請求轉發到指定URL,所以該請求 能夠直接獲得上一個請求的資料,也就是說採用請求轉發,request物件始終存在,不會重新建立。而 sendRedirect()會新建request物件,所以上一個request中的資料會丟失。
兩者更為具體的原理解釋:
-
redirect 會首先發一個response給瀏覽器, 然後瀏覽器收到這個response後再發一個requeset給伺服器,雅思報名費 然後 伺服器發新的response給瀏覽器. 這時頁面收到的request是一個新從瀏覽器發來的. (原理圖可以參見之前Response的部落格)
-
forward 發生在伺服器內部, 在瀏覽器完全不知情的情況下發給了瀏覽器另外一個頁面的response. 這時頁面收到的request不是從瀏覽器直接發來了,可能己經用request.setAttribute在request裡放了資料.在轉到的頁面可直接用request.getAttribute獲得資料。
運用forward方法只能重定向到同一個Web應用程式中的一個資源。而sendRedirect方法可以讓你重定向到任何 URL。
請求重定向位址列會發生變化.請求轉發位址列不發生變化.
請求重定向兩次請求兩次響應.請求轉發一次請求一次響應.
小結:
- 轉發一次請求、一次響應; 重定向 兩次請求 兩次響應
- 轉發只能跳轉站內程式,重定向定向任何站點
- 轉發 URL地址不變 ,重定向URL地址改變
- 轉發 對客戶端不可見,重定向對客戶端可見
- 轉發共享同一個Request中資料,重定向兩次請求,不同Request物件,不能共享Request資料
- 重定向 302 + Location —- 簡寫 sendRedirect
- RequestDispatcher 的 include 方法 用來做頁面佈局 —— <%@include%>
將頁面公共部分抽取出來,通過include 引用到頁面中 —- 更加方便維護