Tomcat的架構(gòu)總的來說是分層次的、可插拔的組件架構(gòu)。分層次是指構(gòu)成Tomcat的組件不是同一級別的,上層組件可以包含子組件,各個組件有其功能范圍,當(dāng)一個組件停止服務(wù)時,不會影響上層組件的服務(wù)??刹灏问侵笇τ诮M件的添加和刪除并不影響服務(wù)器的運(yùn)行。那么為了達(dá)到可插拔的組件架構(gòu),分層次的組件架構(gòu)必成為基礎(chǔ)。
創(chuàng)新互聯(lián)長期為近千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為周寧企業(yè)提供專業(yè)的成都做網(wǎng)站、成都網(wǎng)站建設(shè)、成都外貿(mào)網(wǎng)站建設(shè),周寧網(wǎng)站改版等技術(shù)服務(wù)。擁有十多年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。對于任何服務(wù)器,即使最簡單的實(shí)現(xiàn),從面向?qū)ο笤O(shè)計(jì)(OOD)的角度來說,我們都有必要將“服務(wù)器”這個概念抽象出來,為什么呢?因?yàn)橹挥杏辛诉@個概念,才能談服務(wù)器的實(shí)例,服務(wù)器的功能等等其它概念,此之謂“皮之不存,毛將焉附”。趕巧(其實(shí)是我的想法恰好撞上人家的想法),Tomcat也將“服務(wù)器”抽象為java接口org.apache.catalina.Server,顯然Server應(yīng)該就是最最頂層的組件了。 有了Server這個抽象,很自然的,我們希望它能夠提供對servlet和jsp支持的功能。但是我們發(fā)現(xiàn)這個概念太大了,我們還需再細(xì)化。所以別急,我們還有一些事情要解決。服務(wù)器要提供服務(wù)就必須能夠啟動,當(dāng)然也應(yīng)該能夠停止吧,也就是說服務(wù)器應(yīng)該是有生命的,在啟動時初始化必要的資源,而在停止時將其其銷毀掉。好吧,我們把這個也抽象出來,叫做生命周期接口,tomcat 實(shí)現(xiàn)為org.apache.catalina.Lifecycle.如上所述我們知道Lifecycle需要完成的工作了。 public void start() throws LifecycleException; public void stop() throws LifecycleException; 接下來我們分析服務(wù)器如何來處理客戶端的請求,一般的我們會在瀏覽器中輸入如下格式的請求,http://192.168.8.221:8080/explorer/loginInit.do。對于服務(wù)器來說,要想處理這個請求,就必須監(jiān)聽指定的端口8080,當(dāng)有TCP的請求包來時,建立Socket連接,分析并解析之,然后給客戶端返回響應(yīng)。在這個過程中,我們發(fā)現(xiàn),其實(shí)包含了倆個功能點(diǎn),即監(jiān)聽并接受請求和處理請求。那么我們能否將這倆個功能給抽象出來呢?Tomcat告訴我們,可以。是的,Tomcat將“監(jiān)聽并接收請求”抽象為org.apache.catalina.connector.Connector類,負(fù)責(zé)接受請求;將“處理請求”抽象為“容器” org.apache.catalina.Container,負(fù)責(zé)處理Connector傳遞過來的請求。 Ok,到此,我們分析構(gòu)建的簡單服務(wù)器模型出來了,Server由Connector組件和Container組件結(jié)合提供web服務(wù)。 有了這個模型后,要實(shí)現(xiàn)一個簡單的Server已經(jīng)很簡單了,但是在實(shí)現(xiàn)Container時,我們還是要做很多事情,如當(dāng)來請求,我們怎么知道該請求對應(yīng)得虛擬主機(jī),以及請求的那個應(yīng)用,應(yīng)該交給那個servlet對象來處理?這樣看來,Container還是太大了,需要細(xì)化。根據(jù)Servlet規(guī)范,我們知道,servlet屬于某個應(yīng)用,且有上下文環(huán)境,Container要根據(jù)應(yīng)用上下文環(huán)境初始化servlet,然后根據(jù)servlet映射調(diào)用servlet的service方法。在這里“應(yīng)用上下文環(huán)境”的概念很重要,Tomcat將其抽象為org.apache.catalina.Context,Context繼承了Container接口。對于虛擬主機(jī),Tomcat將其抽象為org.apache.catalina.Host,Host繼承了Container接口。 好了,有了這些概念,我們再回顧一下請求的處理過程:瀏覽器發(fā)出請求,Connector接受請求,將請求交由Container處理,Container查找請求對應(yīng)的Host并將請求傳遞給它,Host拿到請求后查找相應(yīng)的應(yīng)用上下文環(huán)境,準(zhǔn)備servlet環(huán)境并調(diào)用service方法。 現(xiàn)在,我們的服務(wù)器模型變成了如圖3所示了。 但是在Tomcat的實(shí)現(xiàn)體系中還有一個Engine的接口,Engine也繼承了Container接口,那么這個接口什么用呢?設(shè)計(jì)Engine的目的有倆個目的,一,當(dāng)希望使用攔截器查看(過濾或預(yù)處理)每個請求時,Engine是個很好的攔截點(diǎn)。二,當(dāng)希望多個虛擬Host共享一個Http的Connector時,Engine是個很好的門面。所以,Engine接口是作為頂級Container組件來設(shè)計(jì)的,其作用相當(dāng)于一個Container的門面。有了Engine,請求的處理過程變?yōu)椋簽g覽器發(fā)出請求,Connector接受請求,將請求交由Container(這里是Engine)處理,Container(Engine來擔(dān)當(dāng))查找請求對應(yīng)的Host并將請求傳遞給它,Host拿到請求后查找相應(yīng)的應(yīng)用上下文環(huán)境,準(zhǔn)備servlet環(huán)境并調(diào)用service方法。再看看服務(wù)器的模型,如圖4.到目前,我們碰到的組件類型有Connector和Container,其實(shí),這也就是Tomcat的核心組件。如圖4,一組Connector和一個Container有機(jī)的組合在一起構(gòu)成Server,就可以提供服務(wù)了,對于Tomcat來說,主要是提供Servlet服務(wù),那么也就是說Tomcat服務(wù)器也可以提供其它服務(wù)了?是的,Tomcat將“一組Connector和一個Container有機(jī)的組合”抽象為“服務(wù)”接口org.apache.catalina.Service,然而,這些服務(wù)實(shí)例彼此獨(dú)立,僅僅共享JVM的基礎(chǔ)設(shè)施,如系統(tǒng)類路徑。 進(jìn)一步的,我們得到了服務(wù)器的框架模型,如圖5. 由圖5,我們知道,對于Tomcat服務(wù)器來說,除了Server代表它自己以外,其它組件都是功能組件,都有其職責(zé)范圍。Service為最頂層的組件,可以添加Connector和Container組件。Engine是Container的最頂層組件,可以添加Host組件,但不能添加父組件。Host組件的父組件是Engine,Host下面包含有Context組件。 接下來看看標(biāo)準(zhǔn)的Tomcat體系結(jié)構(gòu),如圖6. 比較圖5和圖6.我們發(fā)現(xiàn),還有很多輔助組件沒有抽象出來。當(dāng)然,隨著需求的一步步加深,我的分析也會一步步深入,這些個組件也會慢慢浮出水面。