servlet的生命週期

自定義servlet是繼承的HttpServlet,HttpServlet繼承自GenericServlet,GenericServlet實現的javax.servlet. 這裏要注意的是,GenericServlet是一個通用的,不特定於任何協議的Servlet,它實現了Servlet接口。而HttpServlet繼承於GenericServlet,因此HttpServlet也實現了Servlet接口。所以我們定義Servlet的時候只需要繼承HttpServlet即可。而HttpServlet是特定於HTTP協議的類,所以HttpServlet中實現了service()方法,並將請求ServletRequest、ServletResponse 強轉爲HttpRequest 和 HttpResponse。

Servlet接口,此接口的主要定義方法如下:

void init(ServletConfig var1) throws ServletException;

ServletConfig getServletConfig();

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

String getServletInfo();

void destroy();

在代碼中,Servlet生命週期由接口javax.servlet.Servlet定義。所有的Java Servlet 必須直接或間接地實現javax.servlet.Servlet接口,這樣才能在Servlet Engine上運行。javax.servlet.Servlet接口定義了一些方法,在Servlet 的生命週期中,這些方法會在特定時間按照一定的順序被調用。

下面是主要方法的的說明

  1. init()方法

    在Servlet的生命週期中,僅執行一次init()方法,它是在服務器裝入Servlet時執行的,可以配置服務器,以在啓動服務器或客戶機首次訪問Servlet時裝入Servlet。無論有多少客戶機訪問Servlet,都不會重複執行init();

  2. service()方法

    它是Servlet的核心,每當一個客戶請求一個HttpServlet對象,該對象的Service()方法就要調用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應”(ServletResponse)對象作爲參數。在HttpServlet中已存在Service()方法。默認的服務功能是調用與HTTP請求的方法相應的do功能。

  3. destroy()方法

    僅執行一次,在服務器端停止且卸載Servlet時執行該方法,有點類似於C++的delete方法。一個Servlet在運行service()方法時可能會產生其他的線程,因此需要確認在調用destroy()方法時,這些線程已經終止或完成。

所以servlet生命週期分爲三個階段:

  1. 初始化階段 調用init()方法
  2. 響應客戶請求階段  調用service()方法
  3. 終止階段  調用destroy()方法

當啓動Servlet容器時,容器首先查找一個配置文件web.xml,這個文件中記錄了可以提供服務的Servlet。每個Servlet被指定一個Servlet名,也就是這個Servlet實際對應的Java的完整class文件名。Servlet容器會爲每個自動裝入選項的Servlet創建一個實例。所以,每個Servlet類必須有一個公共的無參數的構造器 servlet在servlet Engine上的運行加載順序:

不存在的servlet實例————>容器裝載servlet ————>創建servlet實例————>初始化servlet:調用servlet的init()方法————>處理業務:調用serlvet實例的service()方法————>結束servlet:調用實例的destroy()方法

初始化階段: 當servlet實例化時,servlet容器將調用每個servlet的init()方法來實例化每個實例,執行完每個init()方法後,servlet處於“已初始化”狀態。 對於servlet對象創建的時機: 根據網上資料所說有三種:

1、Servlet容器啓動時:讀取web.xml配置文件中的信息,構造指定的Servlet對象,創建ServletConfig對象,同時將ServletConfig對象作爲參數來調用Servlet對象的init方法。

2、在Servlet容器啓動後:客戶首次向Servlet發出請求,Servlet容器會判斷內存中是否存在指定的Servlet對象,如果沒有則創建它,然後根據客戶的請求創建HttpRequest、 HttpResponse對象,從而調用Servlet 對象的service方法。

3、Servlet的類文件被更新後,重新創建Servlet Servlet容器在啓動時自動創建Servlet,這是由在web.xml文件中爲Servlet設置的<load-on-startup>屬性決定

對於第一種開始並不瞭解,經查看源碼知道,是在GenericServlet的init()方法裏實現的,源碼如下:

public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
}

config的加載配置信息源碼:

public String getInitParameter(String name) {
            ServletConfig sc = this.getServletConfig();
        if(sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameter(name);
        }
    }

    public Enumeration getInitParameterNames() {
        ServletConfig sc = this.getServletConfig();
        if(sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameterNames();
        }
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public ServletContext getServletContext() {
        ServletConfig sc = this.getServletConfig();
        if(sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletContext();
        }
    }

第三種關於<load-on-statup> ...... </load-on-statup>要注意一點是:參數小於0即負數時,web容器啓動時不做實例化處理,servlet首次被 調用時才做實例化,這種情況和沒有設置<load-on-statup>時是一樣的;參數大於0時,web容器啓動時做實例化處理,順序是從小到大,正整數小的先被實例化;參數等於0時,web容器啓動時做實例處理,相當於是最大整數,因此web容器啓動時,最後被實例化; 注意:在web.xml文件中配置<load-on-statup>的servlet,很可能沒有配置<servlet-mapping>,這樣我們無法通過url的方式訪問這個servlet,這種servlet通常是需要在servlet容器啓動自動加載,完成一些全局性的初始化工作

響應客戶請求階段: servlet被初始化以後,就處於能響應請求的就緒狀態,每個對servlet的請求由一個Servlet Request對象代表,servlet給客戶端的響應由一個servlet Response對象代表。對於用戶的到達請求,服務器都會創建特定於請求的Servlet Request和servlet Response對象,然而調用被請求servlet的service()方法。service()方法從ServletRequest對象獲取客戶請求信息,並通過ServletResponse對象向客戶返回響應信息。

ServletRequest和ServletResponse對象在HttpServlet裏被強轉爲HttpServletRequest和HttpServletResponse,源碼:

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest request;
    HttpServletResponse response;
    try {
        request = (HttpServletRequest)req;
        response = (HttpServletResponse)res;
    } catch (ClassCastException var6) {
        throw new ServletException("non-HTTP request or response");
    }

    this.service(request, response);
}

對於Service()方法,同一個Service()方法可能被多個用戶同時訪問,這樣也會出現併發問題,所以在對同一文件的讀寫操作時最好加線程同步,但這樣的話會降低項目的整體性能 ,具體需求具體分析

終止階段: 當WEB應用被終止,或Servlet容器終止運行,或Servlet容器重新裝載Servlet新實例時,Servlet容器會先調用Servlet的destroy()方法,在destroy()方法中可以釋放掉Servlet所佔用的資源。

最後說點Servlet與JSP的比較: jsp在被web容器加載後生成的class反編譯後是類servlet,可以看成是servlet,jsp是直觀的網頁模式,servlet雖然可以生成網頁,但邏輯複雜,也不直觀,servlet一般用於處理業務

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章