Servlet繼承關係和生命週期

一、Servlet的繼承關係

假如現有咱們自定義的一個Servlet,繼承HttpServlet,那麼實際上它的繼承鏈以下圖:web

 

能夠看到,核心的部分在於:服務器

  • 兩個頂級接口
    • Servlet
    • ServletConfig
  • 接口的實現類
    • GenericServlet
  • 基於HTTP協議的實現類
    • HttpServlet

 

咱們剝離一下,把不須要看的去掉,再把方法顯示一下,可清晰知道Servlet的總體繼承關係以下:多線程

 

 其中重點摘錄部分進行說明:this

 

  • 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()方法體卻爲空,爲何?spa

 

 

 

 

1線程

public void init(ServletConfig config) throws ServletException {

23d

   this.config = config;

3xml

   this.init();

4對象

}
 

 

 

1blog

public void init() throws ServletException {

2

 

3

}

 

首先,爲了方便可以在其餘地方也能直接使用ServletConfig對象,而不單單侷限在init(ServletConfig config)方法中,因此建立一個私有的成員變量config,在init(ServletConfig config)方法中就將其賦值給config,這樣一來,GenericServlet和其子類均可以調用其getServletConfig()方法來獲取ServletConfig對象了。

 

之因此有空的init(),實際上就是爲了後續的擴展和重寫,有須要的狀況下去覆蓋init()而不是去覆蓋init(ServletConfig config),由於後者一旦覆蓋,就沒法經過上述的方法在其餘地方便捷地調用getServletConfig方法獲取ServletConfig對象了。

 

實際上,Servlet繼承關係文字描述起來反而複雜,結合繼承圖和源碼查看,能更加清晰明瞭,這裏進行了大概的闡述,更多細節的話須要查看源碼或者API了,此處再也不詳細展開。

 

二、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()方法
相關文章
相關標籤/搜索