1. 程式人生 > >Servlet的生命週期、工作原理和一次請求響應過程

Servlet的生命週期、工作原理和一次請求響應過程

一、Servlet的生命週期

Servlet的生命週期分為4個階段:例項化- ->初始化- ->執行處理- ->銷燬
(1)例項化——new:伺服器第一次被訪問時,載入一個Servlet容器,而且只會被載入一次
(2)初始化——init:建立完Servlet容器後,會呼叫僅執行一次的init()初始化方法,用於初始化Servlet物件,無論多少臺客戶端在伺服器執行期間訪問都不會再執行init()方法。

可以在繼承的GenericServlet這個抽象類中看到初始化方法:

public void init() throws ServletException {
    }

而在我們的Servlet類中應繼承呼叫該方法:

public void init() throws ServletException {
        super.init();
    }

(3)執行處理——service()方法:HttpServlet的抽象類提供了doGet()、doPost()……等方法。對應了request請求的傳送方法,與之相匹配:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported"
); if (protocol.endsWith("1.1")) { resp.sendError(405, msg); } else { resp.sendError(400, msg); } } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_post_not_supported"
); if (protocol.endsWith("1.1")) { resp.sendError(405, msg); } else { resp.sendError(400, msg); } }

(4)銷燬——destroy:在伺服器關閉或重啟時,Servlet會呼叫destroy方法來銷燬,將Servlet容器標記為垃圾檔案,讓GC做回收處理。我們編寫的Servlet是呼叫了GenericServlet抽象類的destroy方法:

@Override
    public void destroy() {
        super.destroy();
    }

二、Servlet的工作原理

1、首先簡單解釋一下Servlet接收和響應客戶請求的過程:
客戶傳送一個請求,Servlet是呼叫service()方法對請求進行響應的,通過原始碼可見,service()方法中對請求的方式進行了匹配。選擇呼叫doGet,doPost等這些方法,然後再進入對應的方法中呼叫邏輯層的方法,實現對客戶的響應。在Servlet介面和GenericServlet中是沒有doGet()、doPost()等等這些方法的,HttpServlet中定義了這些方法,但是都是返回error資訊,所以,我們每次定義一個Servlet的時候,都必須實現doGet或doPost等這些方法。

2、每一個自定義的Servlet都必須實現Servlet的介面,Servlet介面中定義了五個方法,其中比較重要的三個方法涉及到Servlet的生命週期,分別是上文提到的init(),service(),destroy()方法。GenericServlet是一個通用的,不特定於任何協議的Servlet,它實現了Servlet介面。而HttpServlet繼承於GenericServlet,因此HttpServlet也實現了Servlet介面。所以我們定義Servlet的時候只需要繼承HttpServlet即可。

package javax.servlet;

import java.io.IOException;

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

3、Servlet介面和GenericServlet是不特定於任何協議的,而HttpServlet是特定於HTTP協議的類,所以HttpServlet中實現了service()方法,並將請求ServletRequest、ServletResponse 強轉為HttpRequest 和 HttpResponse。
以上三點參考:Servlet的工作原理

4、另外,Servlet是單例模式,執行緒是不安全的,因此在service()方法中儘量不要操作全域性變數。但實際上,可以通過使用session和application來代替全域性變數,只是會加大伺服器負載。

三、Servlet處理請求的過程

  1. 客戶端傳送請求給伺服器。
  2. 容器根據請求及web.xml判斷對應的Servlet是否存在,如果不存在則返回404
  3. 容器根據請求及web.xml判斷對應的Servlet是否已經被例項化,若是相應的Servlet沒有被例項化,則容器將會載入相應的Servlet到Java虛擬機器並例項化
  4. 呼叫例項物件的service()方法,並開啟一個新的執行緒去執行相關處理。呼叫servce方法,判斷是呼叫doGet方法還是doPost方法
  5. 業務完成後響應相關的頁面傳送給客戶端。