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



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()方法體卻為空,為什么?

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

}

首先,為了方便能夠在其他地方也能直接使用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()方法
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM