一. 請求轉發的細節
1. forward方法用于将請求轉發到RequestDispatcher對象封裝的資源。
2. 如果在調用forward方法之前,在Servlet程式中寫入的部分内容已經被真正地傳送到了用戶端,forward方法
将抛出IllegalStateException異常。
3. 如果在調用forward方法之前向Servlet引擎的緩沖區中寫入了内容,隻要寫入到緩沖區中的内容還沒有被真正
輸出到用戶端,forward方法就可以被正常執行,原來寫入到輸出緩沖區中的内容将被清空,但是,已寫入到
HttpServletResponse對象中的響應頭字段資訊保持有效。
二. 請求轉發與請求重定向
1. 請求轉發
一個web資源收到用戶端請求後,通知伺服器去調用另外一個web資源進行處理,稱之為請求轉發。
2. 請求重定向
一個web資源收到用戶端請求後,通知浏覽器去通路另外一個web資源,稱之為請求重定向。
三. 請求轉發與請求重定向的差別
1. 差別:
(1) RequestDispatcher.forward方法隻能将請求轉發給同一個WEB應用中的元件;而
HttpServletResponse.sendRedirect 方法還可以重定向到同一個站點上的其他應用程式中的資源,甚至是使用
絕對URL重定向到其他站點的資源。
(2) 如果傳遞給HttpServletResponse.sendRedirect 方法的相對URL以“/”開頭,它是相對于整個WEB站點的
根目錄;如果建立RequestDispatcher對象時指定的相對URL以“/”開頭,它是相對于目前WEB應用程式的根目
錄。
(3) 調用HttpServletResponse.sendRedirect方法重定向的通路過程結束後,浏覽器位址欄中顯示的URL會發生
改變,由初始的URL位址變成重定向的目标URL;調用RequestDispatcher.forward 方法的請求轉發過程結束
後,浏覽器位址欄保持初始的URL位址不變。
(4) HttpServletResponse.sendRedirect方法對浏覽器的請求直接作出響應,響應的結果就是告訴浏覽器去重新
發出對另外一個URL的通路請求;RequestDispatcher.forward方法在伺服器端内部将請求轉發給另外一個資
源,浏覽器隻知道發出了請求并得到了響應結果,并不知道在伺服器程式内部發生了轉發行為。
(5) RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬
于同一個通路請求和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的
request對象和response對象,它們屬于兩個獨立的通路請求和響應過程。
2. 總結:
(1) 轉發
① 位址欄不會改變;
② 轉發隻能轉發到目前web應用内的資源;
③ 在轉發過程中,可以把資料儲存到request域對象中;
(2) 重定向
① 位址欄會改變,變成重定向到的位址;
② 重定向可以跳轉到目前web應用,或其他web應用,甚至是外部域名網站;
③ 在重定向的過程,不能把資料儲存到request域對象中。
注意:如果要使用request域對象進行資料共享,隻能用轉發技術。
四. 執行個體
1. 執行個體
(1) ForwardDemo1
/*
* 轉發(效果:跳轉頁面)
*/
@WebServlet("/ForwardDemo1")
public class ForwardDemo1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 儲存資料到request域對象
*/
request.setAttribute("name", "Jack");
/*
* 注意:不能轉發到目前web應用以外的資源
*/
/*
RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/GetDateServlet");
rd.forward(request, response);
*/
this.getServletContext().getRequestDispatcher("/GetDateServlet").forward(request, response);//注釋内容的簡寫
}
}
(2) RedirectDemo1
/*
* 重定向
*/
@WebServlet("/RedirectDemo1")
public class RedirectDemo1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 儲存資料到request域對象
*/
request.setAttribute("name", "Rose");
// 重定向
/*
* 注意:可以跳轉到web應用内或其他web應用,甚至其他外部域名。
*/
response.sendRedirect("/zw_Servlet/GetDateServlet");
}
}
(3) GetDateServlet
@WebServlet("/GetDateServlet")
public class GetDateServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 從request域對象中擷取資料
*/
String name = (String) request.getAttribute("name");
System.out.println("name=" + name);
}
}
2. 運作結果
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1zYE1ENnpXT0UleNdXRUFGbkhFZvB3MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zN3MzMwYzMyEzNyMDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
3. 存在的問題與解決
(1) 疑問:為什麼通路ForwardDemo1的時候可以讀取出name=Jack,而通路RedirectDemo1的時候卻讀取出
name=null?
(2) 分析:
tomcat伺服器中有轉發ForwardDemo1和重定向RedirectDemo1,它們都要跳轉到GetDataServlet。
①當使用者通路ForwardDemo1的時候,轉發的原理是:
使用者發送request對象給ForwardDemo1,而ForwardDemo1把request對象轉發給目标資源GetDateServlet,
轉發是伺服器内部的行為,轉發的這個request對象和使用者發送的request對象是同一個對象而在
ForwardDemo1中儲存了資料,儲存的資料放在了request對象中去,把資料發到另外一個Servlet中,那麼另外
一個Servlet是可以拿到這個資料的。因為是同一個請求。
②當使用者通路RedirectDemo1的時候,重定向的原理是:
當使用者發送請求request給RedirectDemo1,那麼RedirectDemo1先進行資料儲存,然後立刻發送一個響應給用
戶,響應的内容是302+location,接着使用者請求GetDateServlet,這個GetDateServlet再傳回一個響應給用
戶。但是我們是在GetDateServlet中去拿出資料,而第二次的請求和第一次的請求是完全不同的請求對象,是以
第一次存的資料,第二次根本拿不了。
4. 總結:
在轉發的過程中,可以把資料存放到request域對象中去,但是在重定向的過程中,不能把資料存放到request域
對象中去。