1. 程式人生 > >[03] Servlet繼承關系和生命周期

[03] Servlet繼承關系和生命周期

height div ava alt doget .com tps 設定 詳細


1、Servlet的繼承關系

假如現有我們自定義的一個Servlet,繼承HttpServlet,那麽實際上它的繼承鏈如下圖:技術分享 可以看到,核心的部分在於:
  • 兩個頂級接口
    • Servlet
    • ServletConfig
  • 接口的實現類
    • GenericServlet
  • 基於HTTP協議的實現類
    • HttpServlet

我們剝離一下,把不需要看的去掉,再把方法顯示一下,可清晰知道Servlet的整體繼承關系如下技術分享
其中重點摘錄部分進行說明:
  • ServletConfig Servlet的配置信息,常用來在Servlet初始化時進行信息傳遞
    • getServletContext() 獲取Servlet運行的上下文環境對象,可以獲取對應信息(如Servlet路徑),存取容量級的變量
    • getInitParameter(String name) 獲取初始化參數(web.xml中配置的init-param)

  • GenericServlet 一般的Servlet,實現了Servlet和ServletConfig接口
    • init(ServletConfig config) 初始化方法,方法中調用了init()
    • init() 初始化方法,方法體為空,主要用於自定義Servlet的覆蓋
    • service(ServletRequest request, ServletResponse response) 抽象方法service,要求繼承類實現
    • destory() Servlet銷毀前要執行的方法

  • HttpServlet 基於HTTP協議的實現類
    • service(ServletRequest request, ServletResponse response) 實現了GenericServlet的抽象方法,調用了service(HttpServletRequest, HttpServletResponse)
    • service(HttpServletRequest request, HttpServletResponse response) 根據請求的不同調用了doGet或doPost方法
    • doGet() 處理GET方式的請求
    • doPost() 處理POST方式的請求

其中稍微提一下,在GenericServlet中有個init(ServletConfig config)方法,調用了init()方法,但是init()方法體卻為空,為什麽?
  1. public
    void init(ServletConfig config) throws ServletException {
  2. this.config = config;
  3. this.init();
  4. }
  1. public void init() throws ServletException {
  2. }

首先,為了方便能夠在其他地方也能直接使用ServletConfig對象,而不僅僅局限在init(ServletConfig config)方法中,所以創建一個私有的成員變量config,在init(ServletConfig config)方法中就將其賦值給config,這樣一來,GenericServlet和其子類都可以調用其getServletConfig()方法來獲取ServletConfig對象了。
之所以有空的init(),實際上就是為了後續的擴展和重寫,有需要的情況下去覆蓋init()而不是去覆蓋init(ServletConfig config),因為後者一旦覆蓋,就無法通過上述的方法在其他地方便捷地調用getServletConfig方法獲取ServletConfig對象了。
實際上,Servlet繼承關系文字描述起來反而復雜,結合繼承圖和源碼查看,能更加清晰明了,這裏進行了大概的闡述,更多細節的話需要查看源碼或者API了,此處不再詳細展開。

2、Servlet的生命周期

Servlet之間的啟動是有先後順序的,這可以在web.xml中通過<load-on-startup>標簽進行設定,參數為數字,表示了啟動的順序。啟動順序的默認值是0:
  • load-on-startup --> 0:Servlet被訪問時才進行實例化
  • load-on-startup --> other:在容器啟動時進行Servlet實例化

即是說,默認不配置該參數的情況下,Servlet只有再被訪問時才會實例化;配置了參數以後,根據參數按順序在容器啟動時就將Servlet實例化
然後,Servlet的生命周期,其實說來也簡單:
  • 容器在加載Servlet的時候,會執行其init()方法
  • 當接收請求的時候,會調用service(ServletReqeust request, ServletResponse response)方法,繼而調用doGet或doPost方法
  • 在服務器關閉之前,會調用Servlet的destory()方法

即:
  • init()
  • doGet() / doPost()
  • destory()

實際上,完整一點來說:
  • 初始化
    • 構造方法
    • init(ServletConfig config)
    • init()
  • 提供服務
    • service(ServletRequest request, ServletResponse response)
    • doGet() / doPost()
  • 銷毀
    • destory()

(寫得有點啰嗦...)技術分享 最後簡單總結下要點:
  • Servlet只初始化一次,它是單例的,只有一個實例,通過多線程訪問。即Servlet是多線程單實例的
  • 實例化過程中,先調用構造方法,再調用init方法,所以初始化操作可以覆蓋寫到init方法中
  • 請求方式不同會調用doGet()或doPost()方法
  • 根據實際情況在Servlet銷毀前調用其destroy()方法

[03] Servlet繼承關系和生命周期