1、執行環境
tomcat 版本:8.0.x
編譯工具:ant
執行ide:idea13.1
2、tomcat架構組成
如下圖所示:
server: 其實就是background程式, 在tomcat裡面的server的用處是啟動和監聽服務端事件(諸如重啟、關閉等命令。
service: 在tomcat裡面,service是指一類問題的解決方案。 通常我們會預設使用tomcat提供的:tomcat-standalone 模式的service。 在這種方式下的service既給我們提供解析jsp和servlet的服務, 同時也提供給我們解析靜態文字的服務。
connector: tomcat都是在容器裡面處理問題的, 而容器又到**去取得輸入資訊呢?
connector就是專幹這個的。 他會把從socket傳遞過來的資料, 封裝成request, 傳遞給容器來處理。
通常我們會用到兩種connector,一種叫http connectoer, 用來傳遞http需求的。 另一種叫ajp, 在我們整合apache與tomcat工作的時候,apache與tomcat之間就是通過這個協議來互動的。 (說到apache與tomcat的整合工作, 通常我們的目的是為了讓apache 獲取靜態資源, 而讓tomcat來解析動態的jsp或者servlet。)
container: 當http connector把需求傳遞給頂級的container: engin的時候, 我們的視線就應該移動到container這個層面來了。
在container這個層, 我們包含了
3種容器:engin, host, context.
engin: 收到service傳遞過來的需求, 處理後, 將結果返回給service( service 是通過connector 這個媒介來和engin互動的).
host: engin收到service傳遞過來的需求後,不會自己處理, 而是交給合適的host來處理。
host在這裡就是虛擬主機的意思, 通常我們都只會使用乙個主機,既「localhost」本地機來處理。
context: host接到了從host傳過來的需求後, 也不會自己處理, 而是交給合適的context來處理。
3、tomcat啟動流程
1> 初始化自定義的classloader
• 根據
catalina.properties
的配置讀取要載入的
class
的路徑及
jar包;
• 將上述路徑轉化為
url集合;
• 呼叫
accesscontroller.doprivileged
生成classloader;
• 設定當前上下文及對應的classloader。
2>使用digester技術裝配tomcat各個容器與元件
• 建立乙個
digester
,並且配置好所有需要用到的
actions;
• 讀取server.xml
檔案並將其轉換為
inputsource
,並提供給
digester
來解析成例項物件,並封裝在
catalina
裡面;
• 最後catalina
觸發初始化動作,開始逐層初始化。
3> 初始化
依次通過設定new、initializing、initialized這三個狀態來表示初始化當前元件的完成。依次是server->service->engine->host->context->http connector->ajp connector。先是server初始化開始,然後是service,然後依次將裡面的container初始化,然後初始化connector,其中也會初始化各種listener、manger、logger等,最後整個server才算初始化完成。在初始化stantardengine時會建立乙個執行緒池,用來處理http請求,但此時還未啟動執行緒。
4> 服務的啟動
啟動server及service
每個元件或服務的啟動流程:設定starting_prep狀態,呼叫lifecyclebase的star的方法、startinternal的方法中會設定成starting狀態,最後設定started狀態;其中startinternal方法的呼叫是其擴充套件點,按照上述流程會呼叫其內層的元件,直至所有服務或元件啟動完畢。其實初始化的過程也是類似,只是呼叫的方法不一樣而已。
啟動 engine(容器)
startinternal的方法中會有各個元件自己的實現內容。從engine的啟動開始(容器的啟動),有所區別。它首先會啟動realm服務用來驗證配置檔案,使用者名稱、密碼等。然後將engine的所有容器都放到future裡面,最後以非同步的方式啟動其子容器,然後呼叫pipeline,執行valve鏈,然後設定starting狀態,然後啟動乙個執行緒來對當前classloader的載入進行監聽從而實現可配置的熱部署。
啟動mconnectors:
是儲存了
host
及service
的對映關係,以保證處理請求事能找到對應的服務來處理。會按照server.xml的配置來建立指定最小和最大執行緒數的執行緒池,來接收並處理請求,超過的執行緒數就會排隊,超過排隊執行緒數的就會被丟棄。
每個容器裡面都會定義乙個pipeline,裡面會放入各種valve,每個valve都會對request進行過濾、校驗等,最後都會指定下一級處理的子容器,除非到達最後一級容器context。
4、tomcat處理一次請求的過程
假設來自客戶的請求為:
1) 請求被傳送到本機埠
8080
,被在那裡偵聽的coyote http/
1.1connector獲得 2
) connector把該請求交給它所在的service的engine來處理,並等待來自engine的回應 3
) engine獲得請求localhost/test/index.jsp,匹配它所擁有的所有虛擬主機host 4
) engine匹配到名為localhost的host(即使匹配不到也把請求交給該host處理,因為該host被定義為該engine的預設主機) 5
) localhost host獲得請求/test/index.jsp,匹配它所擁有的所有context,此處為最長匹配 6
) host匹配到路徑為/test的context(如果匹配不到就把該請求交給路徑名為
""的context去處理)
7) path=
"/test" 8
) context匹配到url pattern為*.jsp的servlet,對應於jspservlet類 9
) 構造httpservletrequest物件和httpservletresponse物件,作為引數呼叫jspservlet的doget或dopost方法
10)context把執行完了之後的httpservletresponse物件返回給host
11)host把httpservletresponse物件返回給engine
12)engine把httpservletresponse物件返回給connector
13)connector把httpservletresponse物件返回給客戶browser
5、tomcat用到的主要設計模式
門面設計模式:tomcat在將http請求封裝成request、response物件時,並不需要其所有的資訊,所以自定義乙個物件,將httprequest、http
response作為該物件的成員變數,然後通過這2個物件來實現自己需要的方法,避免暴露不必要的資訊給外部的呼叫類。
命令模式(模板設計模式
):所有元件都會實現同乙個抽象類,像初始化、初始化完成等操作,又共同的抽象類完成,而設定內部狀態的操作,由各個元件自己去實現。
責任鏈模式:所有容器的pipeline的實現,每個pipeline都有多個valve的定義,用來做一些過濾、校驗的工作,並且在非最後乙個容器的時候,會再最後乙個valve指定下乙個要接收的容器,從而按指定流程流轉起來。
觀察者模式:所有容器的生命週期的監聽以及每個元件的狀態變化及響應,像整個tomcat的初始化、載入、啟動都會去修改對應元件的狀態,然後將狀態的變化通知給關心此狀態變化的***。
Tomcat原始碼分析
本文將會介紹tomcat的原始碼,並給出一些分析。org.apache.catalina.startup.bootstrap 該類是tomcat啟動的入口類,包含有main方法。它的主要工作包括 引數解析 環境變數讀取 設定 類載入器初始化 通過反射的方式來呼叫catalina。org.apache...
Tomcat 原始碼分析
tomcat 原始碼分析 bootstrap 引導過程 1 初始化自定義的類載入器 common shared catalina 2 建立並例項化第乙個元件類 catalina tomcat 元件體系 server service connector engine host context 實現li...
Tomcat 原始碼分析
server 伺服器的意思,代表整個 tomcat 伺服器,乙個 tomcat 只有乙個 server server 中包含至少乙個 service 元件,用於提供具體服務。這個在配置檔案中也得到很好的體現 port 8005 shutdown shutdown 是在 8005 埠監聽到 shutd...