Tomcat即是一個HTTP服務(wù)器,也是一個servlet容器,主要目的就是包裝servlet,并對請求響應(yīng)相應(yīng)的servlet,純servlet的web應(yīng)用似乎很好理解Tomcat是如何裝載servlet的,但,當使用一些MVC框架時,如 spirngmvc、strusts2,可能就找不出servlet在哪里?其實spring MVC框架就是一整個servlet,在web.xml中配置如下:
<servlet>
...
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
...
而Struts2是基于過濾器,過濾器調(diào)用在servlet之前
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
總體結(jié)構(gòu)用下圖來表示:
Tomcat中主要涉及Server,Service,Engine,Connector,Host,Context組件,,在conf目錄中有一個server.xml文件:
<?xml version='1.0' encoding='utf-8'?>
<Server port="7996" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8090" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="7888" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
Tomcat加載時相應(yīng)組件(容器)的配置參數(shù)都是從這個文件讀進去的,這個文件也是Tomcat性能優(yōu)化的關(guān)鍵。
Server
Server是Tomcat中最頂層的組件,它可以包含多個Service組件。在Tomcat源代碼中Server組件對應(yīng)源碼中的 org.apache.catalina.core.StandardServer 類。StandardServer的繼承關(guān)系圖如下圖所示:
Lifecycle是Tomcat的生命周期接口。保持組件啟動和停止一致的的機制,通過實現(xiàn)org.apache.catalina.Lifecycle接口來實現(xiàn)。
Service
Service組件相當于Connetor和Engine組件的包裝器,它將一個或者多個Connector組件和一個Engine建立關(guān)聯(lián)。上述配置文件中,定義一個叫Catalina的Engine,并將Http,AJP(定向包的協(xié)議)這兩個Connector關(guān)聯(lián)到了這個Engine,注意一個Connetor對應(yīng)處理一種協(xié)議。Service組件對應(yīng)Tomcat源代碼中的org.apache.catalina.core.StandardService,StandardService的繼承關(guān)系圖如下圖所示:
Connector
既然Tomcat需要提供http服務(wù),而我們知道http應(yīng)用層協(xié)議最終都是需要通過TCP層的協(xié)議進行傳遞的,而Connector正是Tomcat中監(jiān)聽TCP網(wǎng)絡(luò)連接的組件,一個Connector會監(jiān)聽一個獨立的端口來處理來自客戶端的連接。缺省的情況下Tomcat提供了如下兩個Connector。我們分別描述一下:
HTTP/1.1
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 上面定義了一個Connector,它缺省監(jiān)聽端口8080,這個端口我們可以根據(jù)具體情況進行改動。connectionTimeout定義了連接超時時間,單位是毫秒,redirectPort定義了ssl的重定向接口,根據(jù)缺省的配置,Connector會將ssl請求重定向到8443端口。
AJP/1.3
AJP表示Apache Jserv Protocol,此連接器將處理Tomcat和Aapache http服務(wù)器之間的交互,這個連接器是用來處理我們將Tomcat和Apache http服務(wù)器結(jié)合使用的情況。假如在同樣的一臺物理Server上面部署了一臺Apache http服務(wù)器和多臺Tomcat服務(wù)器,通過Apache服務(wù)器來處理靜態(tài)資源以及負載均衡的時候,針對不同的Tomcat實例需要AJP監(jiān)聽不同的端口。
Connector對應(yīng)源代碼中的org.apache.catalina.connector.Connector,它的繼承關(guān)系圖如下所示:
Engine
Tomcat中有一個容器的概念,而Engine,Host,Context都屬于Contanier,我們先來說說最頂層的容器Engine.
一個Engine可以包含一個或者多個Host,也就是說我們一個Tomcat的實例可以配置多個虛擬主機。
缺省的情況下<Engine name="Catalina" defaultHost="localhost">定義了一個名稱為Cataline的Engine.Engine對應(yīng)源代碼中的org.apache.catalina.core.StandardEngine,它的繼承關(guān)系圖如下圖所示:
Host
Host定義了一個虛擬主機,一個虛擬主機可以有多個Context,缺省的配置如下:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">….</Host> 其中appBase為webapps,也就是<CATALINA_HOME>\webapps目錄,unpackingWARS屬性指定在appBase指定的目錄中的war包都自動的解壓,缺省配置為true,autoDeploy屬性指定是否對加入到appBase目錄的war包進行自動的部署,缺省為true.
Host對應(yīng)源代碼中的org.apache.catalina.core.StandardHost,它的繼承關(guān)系圖如下所示:
Context
在Tomcat中,每一個運行的webapp其實最終都是以Context的形成存在,每個Context都有一個根路徑和請求URL路徑,Context對應(yīng)源代碼中的org.apache.catalina.core.StandardContext,它的繼承關(guān)系圖如下圖所示:
在Tomcat中我們通常采用如下的兩種方式創(chuàng)建一個Context.下面分別描述一下:
1、在<CATALINA-HOME>\webapps目錄中創(chuàng)建一個目錄,這個時候?qū)⒆詣觿?chuàng)建一個context,默認context的訪問url為http://host:port/dirname
2、conf\server.xml文件中增加context元素。 第二種創(chuàng)建context的方法,我們可以選擇在server.xml文件的<Host>元素,比如我們在server.xml文件中增加如下內(nèi)容:
<Host>
<Valve ...
<Context path="/mypath" docBase="/Users/xxx" reloadable="true">
</Context>
</Host>
</Host>
Valve
Valve中文意思是閥門,Valve是Tomcat中責(zé)任鏈模式的實現(xiàn),通過鏈接多個Valve對請求進行處理。每個容器都有一個流水線Pipeline(過濾器鏈),每個流水線至少有一個閥門。tomcat 默認定義了一個名為org.apache.catalina.valves.AccessLogValve
的Valve,這個Valve負責(zé)攔截每個請求,然后記錄一條訪問日志。