一、Servlet的繼承關係
假如現有咱們自定義的一個Servlet,繼承HttpServlet,那麼實際上它的繼承鏈以下圖:web
能夠看到,核心的部分在於:服務器
- 兩個頂級接口
- 接口的實現類
- 基於HTTP協議的實現類
咱們剝離一下,把不須要看的去掉,再把方法顯示一下,可清晰知道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()
- 銷燬
(寫得有點囉嗦...)
最後簡單總結下要點:
- Servlet只初始化一次,它是單例的,只有一個實例,經過多線程訪問。即Servlet是多線程單實例的
- 實例化過程當中,先調用構造方法,再調用init方法,因此初始化操做能夠覆蓋寫到init方法中
- 請求方式不一樣會調用doGet()或doPost()方法
- 根據實際狀況在Servlet銷燬前調用其destroy()方法