1. 程式人生 > >請求轉發、包含、重定向

請求轉發、包含、重定向

JavaWeb應用的生命週期

啟動階段:載入Web應用的有關資料,建立ServletContext物件,對Filter(過濾器)和一些Servlet進行初始化。

執行時階段:為客戶端提供服務。

終止階段:釋放Web應用所佔用的各種資源。

1.啟動階段

  1. 把web.xml檔案中的資料載入到記憶體中。
  2. 為JavaWeb應用建立一個ServletContext物件
  3. 對所有的Filter進行初始化
  4. 對那些需要在Web應用啟動時就被初始化的Servlet進行初始化。
  1. 執行時階段

所有Servlet都處於待命狀態,隨時響應客戶端的特定請求,提供響應的服務。如果客戶端請求的Servlet還不存在,Servlet容器會先初始化Servlet,然後再呼叫它的service()方法。

  1. 終止階段
  1. 銷燬JavaWeb應用中所有處於執行時狀態的Servlet。
  2. 銷燬JavaWeb應用中所有處於執行時狀態的Filter
  3. 銷燬所有與JavaWeb應用相關的物件(ServletContext),並且釋放Web應用所佔用的相關資源。

Servlet的生命週期

JavaWeb應用的生命週期有Servlet容器(Tomcat)來控制,Servlet的生命週期也由Servlet容器來控制。

  1. 初始化階段
  1. Servlet容器載入Servlet類,把.class檔案中的資料讀入到記憶體當中
  2. Servlet容器建立ServletConfig物件。ServletConfig物件包含了特定Servlet的初始化配置資訊(Servlet的初始引數),此外,Servlet容器還會使得ServletConfig物件與當前Web應用的ServletContext物件關聯。
  3. Servlet容器建立Servlet物件。
  4. 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會進入初始化階段:

  1. 當前Web應用處於執行時階段,特定Servlet被客戶端首次請求訪問,多數Servlet都會在這種情況下被Servlet容器初始化.
  2. 如果在web.xml檔案中為一個Servlet設定了<load-on-startup>元素,當Servlet容器啟動Servlet所屬的Web應用時,便會初始化這個Servlet。
  3. 當Web應用被重新啟動時,Web應用中的所有Servlet都會在特定時間被重新初始化。
  1. 執行時階段

Servlet生命週期中最重要的階段,在這個階段Servlet隨時響應客戶端的請求。當Servlet容器接收到要求訪問特定Servlet的客戶請求時,Servlet容器會建立針對於這個請求的ServletRequest物件和ServletResponse物件,然後呼叫物件的service()方法。Service()方法從ServletRequest物件中獲得客戶請求資訊並處理該請求。

Servlet容器把Servlet生成的響應結果傳送給了客戶,Servlet容器就會銷燬ServletRequest物件和ServletResponse物件。

  1. 銷燬階段

當Web應用被終止時,Servlet容器會先呼叫Web應用中所有Servlet物件的destory()方法,然後再銷燬這些Servlet物件。在destory()方法的實現中,可以釋放Servlet所佔用的資源(關閉檔案 輸入流/輸出流,關閉與資料庫的連線),並銷燬與Servlet物件關聯的ServletConfig物件。

請求轉發和重定向

1.轉發

  1. 請求轉發:一個Web資源(Servlet元件)收到客戶端的請求後,通知伺服器呼叫另一個Web資源來處理請求的操作。

  1. 包含:Servlet(源元件)把其他Web元件(目標元件)生成的響應結果包含到自身的響應結果當中。

請求轉發與包含具有的共同特點。

  1. 源元件和目標元件處理的都是同一個客戶請求,源元件和目標元件共享同一個ServletRequest物件和ServletResponse物件。
  2. 目標元件都可以為Servlet、JSP、HTML文件
  3. 都依賴javax.servlet.RequestDispatcher介面(請求分發器)

public void forward(ServletRequest request, ServletResponse response)

Public void include(ServletRequest request, ServletResponse response)

  1. 一次請求,一次響應。

獲取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介面中定義。

  1. 使用者在瀏覽器端輸入特定URL,請求訪問伺服器端的某個元件
  2. 伺服器端的元件返回一個狀態碼為302的響應結果,該響應結果的含義為:

讓瀏覽器端再請求訪問另一個Web伺服器上,也有可能不在同一個Web伺服器上。

  1. 當瀏覽器端接收到這種響應結果後,再立即自動請求訪問另一個Web元件。
  2. 瀏覽器端接收到來自另一個Web元件的響應結果。

程式碼實現:

  1. Servlet源元件生成的響應結果不會被髮送到客戶端。Response.sendRedirect(String location)方法一律返回狀態碼為302的響應結果,瀏覽器端接收到這種響應結果後,再立即自動請求訪問重定向的目標Web元件,客戶端最後接收到的是目標Web元件的響應結果。
  2. 如果源元件在進行重定向之前,已經提交了響應結果,sendRedirect()方法會丟擲IllegalStateException()異常。
  3. Servlet呼叫response.sendRedirect()方法之後的程式碼塊也會被執行。
  4. 源元件和目標元件不共享同一個ServletRequest物件,因此不共享請求範圍內的共享資料。
  5. 對於response.sendRedirect(String location)方法中的引數location,如果以”/”開頭,表示相對於當前伺服器根路徑的URL,如果以”http://”開頭,表示一個完整的URL
  6. 目標元件不必是同一個伺服器上的同一個Web應用中的元件,可以是任意一個有效的網頁。
  7. 兩次請求,兩次響應,位址列會發生變化。