注:在網(wǎng)上看到一篇文章--《Servlet工作原理》,整理并做了一些筆記
1. 了解 Servlet 容器
首先鸥昏,要從servlet 容器開始电抚。servlet容器,故名思議,就是裝載和管理Servlet的服務端程序盆耽。借用一個前輩的解釋:Servlet與Servlet容器的關系有點像槍和子彈的關系,槍是為子彈而生枚粘,而子彈又讓槍有了殺傷力涩拙。
下圖是Tomcat容器模型:
可以看出 Tomcat 的容器分為四個等級,真正管理 Servlet 的容器是 Context 容器丧慈,一個 Context 對應一個 Web 工程析命, Context 容器如何運行將直接影響 Servlet 的工作方式。
2. Servlet 容器啟動過程
Tomcat7 支持嵌入式功能逃默,增加了一個啟動類 org.apache.catalina.startup.Tomcat鹃愤。創(chuàng)建一個實例對象并調用 start 方法就可以很容易啟動 Tomcat,還可以通過這個對象來增加和修改 Tomcat 的配置參數(shù)完域。下面我們就利用這個 Tomcat 類來管理新增的一個 Context 容器软吐,我們就選擇 Tomcat7 自帶的 examples Web 工程,并看看它是如何加到這個 Context 容器中的吟税。
# 創(chuàng)建一個 Tomcat 實例
Tomcat tomcat = getTomcatInstance();
File appDir = new File(getBuildDirectory(), "webapps/examples");
# 新增一個 Web 應用
tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath());
# 啟動 Tomcat
tomcat.start();
# 調用其中的一個 HelloWorldExample Servlet凹耙,看有沒有正確返回預期的數(shù)據(jù)。
ByteChunk res = getUrl("http://localhost:" + getPort() +
"/examples/servlets/servlet/HelloWorldExample"); assertTrue(res.toString().indexOf("<h1>Hello World!</h1>") > 0);
一個 Web 應用對應一個 Context 容器肠仪,也就是 Servlet 運行時的 Servlet 容器肖抱,添加一個 Web 應用時將會創(chuàng)建一個 StandardContext 容器(StandardContext是Context的標準實現(xiàn)),并且給這個 Context 容器設置必要的參數(shù)异旧,url 和 path 分別代表這個應用在 Tomcat 中的訪問路徑和這個應用實際的物理路徑意述。其中最重要的一個配置是 ContextConfig,這個類將會負責整個 Web 應用配置的解析工作吮蛹。最后將這個 Context 容器加到父容器 Host 中荤崇。
接下去將會調用 Tomcat 的 start 方法啟動 Tomcat,Tomcat 的啟動邏輯是基于觀察者模式設計的潮针,所有的容器都會繼承 Lifecycle 接口术荤,它管理者容器的整個生命周期,所有容器的的修改和狀態(tài)的改變都會由它去通知已經(jīng)注冊的觀察者(Listener)然低。
當 Context 容器初始化狀態(tài)設為 init 時喜每,添加在 Contex 容器的 Listener 將會被調用。ContextConfig 繼承了 LifecycleListener 接口雳攘,它是在調用 addWebapp 時被加入到 StandardContext 容器中带兜。ContextConfig 類會負責整個 Web 應用的配置文件的解析工作。
ContextConfig 的 init 方法將會主要完成以下工作:
1. 創(chuàng)建用于解析 xml 配置文件的 contextDigester 對象
2. 讀取默認 context.xml 配置文件吨灭,如果存在解析它
3. 讀取默認 Host 配置文件刚照,如果存在解析它
4. 讀取默認 Context 自身的配置文件,如果存在解析它
5. 設置 Context 的 DocBase
ContextConfig 的 init 方法完成后喧兄,Context 容器的會執(zhí)行 startInternal 方法无畔,這個方法啟動邏輯比較復雜啊楚,主要包括如下幾個部分:
1. 創(chuàng)建讀取資源文件的對象
2. 創(chuàng)建 ClassLoader 對象
3. 設置應用的工作目錄
4. 啟動相關的輔助類如:logger、realm浑彰、resources 等
5. 修改啟動狀態(tài)恭理,通知感興趣的觀察者(Web 應用的配置)
6. 子容器的初始化
7. 獲取 ServletContext 并設置必要的參數(shù)
8. 初始化“l(fā)oad on startup”的 Servlet