[03] Servlet繼承關系和生命周期
阿新 • • 發佈:2017-09-01
height div ava alt doget .com tps 設定 詳細
我們剝離一下,把不需要看的去掉,再把方法顯示一下,可清晰知道Servlet的整體繼承關系如下:
其中重點摘錄部分進行說明:
其中稍微提一下,在GenericServlet中有個init(ServletConfig config)方法,調用了init()方法,但是init()方法體卻為空,為什麽?
首先,為了方便能夠在其他地方也能直接使用ServletConfig對象,而不僅僅局限在init(ServletConfig config)方法中,所以創建一個私有的成員變量config,在init(ServletConfig config)方法中就將其賦值給config,這樣一來,GenericServlet和其子類都可以調用其getServletConfig()方法來獲取ServletConfig對象了。
之所以有空的init(),實際上就是為了後續的擴展和重寫,有需要的情況下去覆蓋init()而不是去覆蓋init(ServletConfig config),因為後者一旦覆蓋,就無法通過上述的方法在其他地方便捷地調用getServletConfig方法獲取ServletConfig對象了。
實際上,Servlet繼承關系文字描述起來反而復雜,結合繼承圖和源碼查看,能更加清晰明了,這裏進行了大概的闡述,更多細節的話需要查看源碼或者API了,此處不再詳細展開。
即是說,默認不配置該參數的情況下,Servlet只有再被訪問時才會實例化;配置了參數以後,根據參數按順序在容器啟動時就將Servlet實例化。
然後,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()方法
[03] Servlet繼承關系和生命周期