請求轉發、包含、重定向
JavaWeb應用的生命週期
啟動階段:載入Web應用的有關資料,建立ServletContext物件,對Filter(過濾器)和一些Servlet進行初始化。
執行時階段:為客戶端提供服務。
終止階段:釋放Web應用所佔用的各種資源。
1.啟動階段
- 把web.xml檔案中的資料載入到記憶體中。
- 為JavaWeb應用建立一個ServletContext物件
- 對所有的Filter進行初始化
- 對那些需要在Web應用啟動時就被初始化的Servlet進行初始化。
- 執行時階段
所有Servlet都處於待命狀態,隨時響應客戶端的特定請求,提供響應的服務。如果客戶端請求的Servlet還不存在,Servlet容器會先初始化Servlet,然後再呼叫它的service()方法。
- 終止階段
- 銷燬JavaWeb應用中所有處於執行時狀態的Servlet。
- 銷燬JavaWeb應用中所有處於執行時狀態的Filter
- 銷燬所有與JavaWeb應用相關的物件(ServletContext),並且釋放Web應用所佔用的相關資源。
Servlet的生命週期
JavaWeb應用的生命週期有Servlet容器(Tomcat)來控制,Servlet的生命週期也由Servlet容器來控制。
- 初始化階段
- Servlet容器載入Servlet類,把.class檔案中的資料讀入到記憶體當中
- Servlet容器建立ServletConfig物件。ServletConfig物件包含了特定Servlet的初始化配置資訊(Servlet的初始引數),此外,Servlet容器還會使得ServletConfig物件與當前Web應用的ServletContext物件關聯。
- Servlet容器建立Servlet物件。
- Servlet容器呼叫Servlet物件的init(ServletConfig config)方法,在Servlet介面的GenericServlet實現類的init(ServletConfig config)方法中,會建立Servlet物件與ServletConfig物件的關聯關係。
以上步驟建立了Servlet物件和ServletConfig物件,並且Servlet物件與ServletConfig物件關聯,而ServletConfig物件又與當前Web應用的ServletContext物件關聯。當Servlet容器初始化完Servlet後,Servlet物件只要通過getServeltContext()方法就能得到當前Web應用的ServletContext物件。
以下幾種情況,Servlet會進入初始化階段:
- 當前Web應用處於執行時階段,特定Servlet被客戶端首次請求訪問,多數Servlet都會在這種情況下被Servlet容器初始化.
- 如果在web.xml檔案中為一個Servlet設定了<load-on-startup>元素,當Servlet容器啟動Servlet所屬的Web應用時,便會初始化這個Servlet。
- 當Web應用被重新啟動時,Web應用中的所有Servlet都會在特定時間被重新初始化。
- 執行時階段
Servlet生命週期中最重要的階段,在這個階段Servlet隨時響應客戶端的請求。當Servlet容器接收到要求訪問特定Servlet的客戶請求時,Servlet容器會建立針對於這個請求的ServletRequest物件和ServletResponse物件,然後呼叫物件的service()方法。Service()方法從ServletRequest物件中獲得客戶請求資訊並處理該請求。
Servlet容器把Servlet生成的響應結果傳送給了客戶,Servlet容器就會銷燬ServletRequest物件和ServletResponse物件。
- 銷燬階段
當Web應用被終止時,Servlet容器會先呼叫Web應用中所有Servlet物件的destory()方法,然後再銷燬這些Servlet物件。在destory()方法的實現中,可以釋放Servlet所佔用的資源(關閉檔案 輸入流/輸出流,關閉與資料庫的連線),並銷燬與Servlet物件關聯的ServletConfig物件。
請求轉發和重定向
1.轉發
- 請求轉發:一個Web資源(Servlet元件)收到客戶端的請求後,通知伺服器呼叫另一個Web資源來處理請求的操作。
- 包含:Servlet(源元件)把其他Web元件(目標元件)生成的響應結果包含到自身的響應結果當中。
請求轉發與包含具有的共同特點。
- 源元件和目標元件處理的都是同一個客戶請求,源元件和目標元件共享同一個ServletRequest物件和ServletResponse物件。
- 目標元件都可以為Servlet、JSP、HTML文件
- 都依賴javax.servlet.RequestDispatcher介面(請求分發器)
public void forward(ServletRequest request, ServletResponse response)
Public void include(ServletRequest request, ServletResponse response)
- 一次請求,一次響應。
獲取RequestDispatcher物件的兩種方式:
ServletContext的getRequestDispatcher(String path)
Path:必須為絕對路徑,以“/”開頭,表示Web應用的URL入口
ServletRequest的getRequestDispatcher(String path)
Path:絕對路徑和相對路徑都可以
...
// 在request物件中新增msg屬性
request.setAttribute(“msg”,message);
// 把請求轉發給目標元件(servlet)
ServletContext context = getServletContext();
RequestDispatcher dispatcher = context.getRequestDispatcher(“/output”);
....
dispatcher.forward(request,response);
...
dispatcher.forward(request,response)方法的處理流程
清空用於存放響應正文資料的緩衝區
如果目標元件為Servlet或JSP,就呼叫它們的service()方法,把該方法產生的響應結果傳送到客戶端;如果目標元件為檔案系統中的靜態HTML文件,就讀取文件中的資料並把它傳送到客戶端。
由於forward()方法先清空用於存放響應正文資料的緩衝求,因此Servlet源元件生成的響應結果不會被髮送到客戶端,只有目標元件生成的響應結果才會被髮送到客戶端。但是在Tomcat伺服器的控制檯,會顯示呼叫dispatcher.forward(request,response)方法之前及之後的列印語句,及Servlet源元件forward()方法之後的程式碼也會被執行
// 值得注意的是,JSP源元件中<jsp:forward>標籤以後的程式碼不會被執行。
<jsp:forward page=”轉發的目標組建的絕對URL或相對URL”>
如果源元件在進行請求轉發之前,已經提交了響應結果(呼叫ServletResponse.flushBuffer()方法、輸出流的close())方法,forward()方法會丟擲IllegalStateException異常.
2.包含
1. 如果目標元件為Servlet或JSP,就呼叫它們的service()方法,把該方法產生的響應正文新增到源元件的響應結果中;如果目標元件為HTML文件,就直接把文件的內容新增到源元件的響應結果中。
2. 返回到源元件的服務方法中,繼續執行後續程式碼塊
與轉發相比較
源元件與被包含的目標元件的輸出資料都會被新增到響應結果中。
在目標元件中對響應狀態碼或者響應頭所做的修改都會被忽略。
3.重定向
HTTP協議規定了一種重定向機制
sendRedirect()方法在HttpServletResponse介面中定義。
- 使用者在瀏覽器端輸入特定URL,請求訪問伺服器端的某個元件
- 伺服器端的元件返回一個狀態碼為302的響應結果,該響應結果的含義為:
讓瀏覽器端再請求訪問另一個Web伺服器上,也有可能不在同一個Web伺服器上。
- 當瀏覽器端接收到這種響應結果後,再立即自動請求訪問另一個Web元件。
- 瀏覽器端接收到來自另一個Web元件的響應結果。
程式碼實現:
- Servlet源元件生成的響應結果不會被髮送到客戶端。Response.sendRedirect(String location)方法一律返回狀態碼為302的響應結果,瀏覽器端接收到這種響應結果後,再立即自動請求訪問重定向的目標Web元件,客戶端最後接收到的是目標Web元件的響應結果。
- 如果源元件在進行重定向之前,已經提交了響應結果,sendRedirect()方法會丟擲IllegalStateException()異常。
- Servlet呼叫response.sendRedirect()方法之後的程式碼塊也會被執行。
- 源元件和目標元件不共享同一個ServletRequest物件,因此不共享請求範圍內的共享資料。
- 對於response.sendRedirect(String location)方法中的引數location,如果以”/”開頭,表示相對於當前伺服器根路徑的URL,如果以”http://”開頭,表示一個完整的URL
- 目標元件不必是同一個伺服器上的同一個Web應用中的元件,可以是任意一個有效的網頁。
- 兩次請求,兩次響應,位址列會發生變化。