1 - Tomcat Server的組成部分
1.1 - Server
A Server element represents the entire Catalina servlet container. (Singleton)
1.2 - Service
A Service element represents the combination of one or more Connector components that share a single Engine
Service是這樣一個(gè)集合:它由一個(gè)或者多個(gè)Connector組成,以及一個(gè)Engine,負(fù)責(zé)處理所有Connector所獲得的客戶請(qǐng)求
1.3 - Connector
一個(gè)Connector將在某個(gè)指定端口上偵聽(tīng)客戶請(qǐng)求,并將獲得的請(qǐng)求交給Engine來(lái)處理,從Engine處獲得回應(yīng)并返回客戶
TOMCAT有兩個(gè)典型的Connector,一個(gè)直接偵聽(tīng)來(lái)自browser的http請(qǐng)求,一個(gè)偵聽(tīng)來(lái)自其它WebServer的請(qǐng)求
Coyote Http/1.1 Connector 在端口8080處偵聽(tīng)來(lái)自客戶browser的http請(qǐng)求
Coyote JK2 Connector 在端口8009處偵聽(tīng)來(lái)自其它WebServer(Apache)的servlet/jsp代理請(qǐng)求
1.4 - Engine
The Engine element represents the entire request processing machinery associated with a particular Service
It receives and processes all requests from one or more Connectors
and returns the completed response to the Connector for ultimate transmission back to the client
Engine下可以配置多個(gè)虛擬主機(jī)Virtual Host,每個(gè)虛擬主機(jī)都有一個(gè)域名
當(dāng)Engine獲得一個(gè)請(qǐng)求時(shí),它把該請(qǐng)求匹配到某個(gè)Host上,然后把該請(qǐng)求交給該Host來(lái)處理
Engine有一個(gè)默認(rèn)虛擬主機(jī),當(dāng)請(qǐng)求無(wú)法匹配到任何一個(gè)Host上的時(shí)候,將交給該默認(rèn)Host來(lái)處理
1.5 - Host
代表一個(gè)Virtual Host,虛擬主機(jī),每個(gè)虛擬主機(jī)和某個(gè)網(wǎng)絡(luò)域名Domain Name相匹配
每個(gè)虛擬主機(jī)下都可以部署(deploy)一個(gè)或者多個(gè)Web App,每個(gè)Web App對(duì)應(yīng)于一個(gè)Context,有一個(gè)Context path
當(dāng)Host獲得一個(gè)請(qǐng)求時(shí),將把該請(qǐng)求匹配到某個(gè)Context上,然后把該請(qǐng)求交給該Context來(lái)處理
匹配的方法是“最長(zhǎng)匹配”,所以一個(gè)path==""的Context將成為該Host的默認(rèn)Context
所有無(wú)法和其它Context的路徑名匹配的請(qǐng)求都將最終和該默認(rèn)Context匹配
1.6 - Context
一個(gè)Context對(duì)應(yīng)于一個(gè)Web Application,一個(gè)Web Application由一個(gè)或者多個(gè)Servlet組成
Context在創(chuàng)建的時(shí)候?qū)⒏鶕?jù)配置文件$CATALINA_HOME/conf/web.xml和$WEBAPP_HOME/WEB-INF/web.xml載入Servlet類
當(dāng)Context獲得請(qǐng)求時(shí),將在自己的映射表(mapping table)中尋找相匹配的Servlet類
如果找到,則執(zhí)行該類,獲得請(qǐng)求的回應(yīng),并返回
2 - Tomcat Server的結(jié)構(gòu)圖
3 - 配置文件$CATALINA_HOME/conf/server.xml的說(shuō)明
該文件描述了如何啟動(dòng)Tomcat Server
4 - Context的部署配置文件web.xml的說(shuō)明
一個(gè)Context對(duì)應(yīng)于一個(gè)Web App,每個(gè)Web App是由一個(gè)或者多個(gè)servlet組成的
當(dāng)一個(gè)Web App被初始化的時(shí)候,它將用自己的ClassLoader對(duì)象載入“部署配置文件web.xml”中定義的每個(gè)servlet類
它首先載入在$CATALINA_HOME/conf/web.xml中部署的servlet類
然后載入在自己的Web App根目錄下的WEB-INF/web.xml中部署的servlet類
web.xml文件有兩部分:servlet類定義和servlet映射定義
每個(gè)被載入的servlet類都有一個(gè)名字,且被填入該Context的映射表(mapping table)中,和某種URL PATTERN對(duì)應(yīng)
當(dāng)該Context獲得請(qǐng)求時(shí),將查詢mapping table,找到被請(qǐng)求的servlet,并執(zhí)行以獲得請(qǐng)求回應(yīng)
分析一下所有的Context共享的web.xml文件,在其中定義的servlet被所有的Web App載入
5 - Tomcat Server處理一個(gè)http請(qǐng)求的過(guò)程
假設(shè)來(lái)自客戶的請(qǐng)求為:
http://localhost:8080/wsota/wsota_index.jsp
1) 請(qǐng)求被發(fā)送到本機(jī)端口8080,被在那里偵聽(tīng)的Coyote HTTP/1.1 Connector獲得
2) Connector把該請(qǐng)求交給它所在的Service的Engine來(lái)處理,并等待來(lái)自Engine的回應(yīng)
3) Engine獲得請(qǐng)求localhost/wsota/wsota_index.jsp,匹配它所擁有的所有虛擬主機(jī)Host
4) Engine匹配到名為localhost的Host(即使匹配不到也把請(qǐng)求交給該Host處理,因?yàn)樵揌ost被定義為該Engine的默認(rèn)主機(jī))
5) localhost Host獲得請(qǐng)求/wsota/wsota_index.jsp,匹配它所擁有的所有Context
6) Host匹配到路徑為/wsota的Context(如果匹配不到就把該請(qǐng)求交給路徑名為""的Context去處理)
7) path="/wsota"的Context獲得請(qǐng)求/wsota_index.jsp,在它的mapping table中尋找對(duì)應(yīng)的servlet
8) Context匹配到URL PATTERN為*.jsp的servlet,對(duì)應(yīng)于JspServlet類
9) 構(gòu)造HttpServletRequest對(duì)象和HttpServletResponse對(duì)象,作為參數(shù)調(diào)用JspServlet的doGet或doPost方法
10)Context把執(zhí)行完了之后的HttpServletResponse對(duì)象返回給Host
11)Host把HttpServletResponse對(duì)象返回給Engine
12)Engine把HttpServletResponse對(duì)象返回給Connector
13)Connector把HttpServletResponse對(duì)象返回給客戶browser
<!------------------------------------------------>
<web-app>
<!-- 概述:
該文件是所有的WEB APP共用的部署配置文件,
每當(dāng)一個(gè)WEB APP被DEPLOY,該文件都將先被處理,然后才是WEB APP自己的/WEB-INF/web.xml-->
<!-- +-------------------------+ -->
<!-- | servlet類定義部分 | -->
<!-- +-------------------------+ -->
<!-- DefaultServlet 當(dāng)用戶的HTTP請(qǐng)求無(wú)法匹配任何一個(gè)servlet的時(shí)候,該servlet被執(zhí)行
URL PATTERN MAPPING : / -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- InvokerServlet 處理一個(gè)WEB APP中的匿名servlet
當(dāng)一個(gè)servlet被編寫(xiě)并編譯放入/WEB-INF/classes/中,卻沒(méi)有在/WEB-INF/web.xml中定義的時(shí)候
該servlet被調(diào)用,把匿名servlet映射成/servlet/ClassName的形式
URL PATTERN MAPPING : /servlet/* -->
<servlet>
<servlet-name>invoker</servlet-name>
<servlet-class>org.apache.catalina.servlets.InvokerServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- JspServlet 當(dāng)請(qǐng)求的是一個(gè)JSP頁(yè)面的時(shí)候(*.jsp)該servlet被調(diào)用
它是一個(gè)JSP編譯器,將請(qǐng)求的JSP頁(yè)面編譯成為servlet再執(zhí)行
URL PATTERN MAPPING : *.jsp -->
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>WARNING</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<!-- +---------------------------+ -->
<!-- | servlet映射定義部分 | -->
<!-- +---------------------------+ -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>invoker</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<!-- +------------------------+ -->
<!-- | 其它部分,略去先 | -->
<!-- +------------------------+ -->
... ... ... ...
</web-app>
<!----------------------------------->
<!------------------------------------------------------------------------->
<!-- 啟動(dòng)Server 在端口8005處等待關(guān)閉命令 如果接受到"SHUTDOWN"字符串則關(guān)閉服務(wù)器 -->
<Server port="8005" shutdown="SHUTDOWN" debug="0">
<!-- Listener ??? 目前沒(méi)有看到這里 -->
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" debug="0"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" debug="0"/>
<!-- Global JNDI resources ??? 目前沒(méi)有看到這里,先略去 -->
<GlobalNamingResources> ... ... ... ... </GlobalNamingResources>
<!-- Tomcat的Standalone Service Service是一組Connector的集合
它們共用一個(gè)Engine來(lái)處理所有Connector收到的請(qǐng)求-->
<Service name="Tomcat-Standalone">
<!-- Coyote HTTP/1.1 Connector className: 該Connector的實(shí)現(xiàn)類是
org.apache.coyote.tomcat4.CoyoteConnector
port : 在端口號(hào)8080處偵聽(tīng)來(lái)自客戶browser的HTTP1.1請(qǐng)求
minProcessors : 該Connector先創(chuàng)建5個(gè)線程等待客戶請(qǐng)求,每個(gè)請(qǐng)求由一個(gè)線程負(fù)責(zé)
maxProcessors : 當(dāng)現(xiàn)有的線程不夠服務(wù)客戶請(qǐng)求時(shí),若線程總數(shù)不足75個(gè),則創(chuàng)建新線程來(lái)處理請(qǐng)求
acceptCount : 當(dāng)現(xiàn)有線程已經(jīng)達(dá)到最大數(shù)75時(shí),為客戶請(qǐng)求排隊(duì) 當(dāng)隊(duì)列中請(qǐng)求數(shù)超過(guò)100時(shí),后來(lái)的請(qǐng)求返回Connection refused錯(cuò)誤
redirectport : 當(dāng)客戶請(qǐng)求是https時(shí),把該請(qǐng)求轉(zhuǎn)發(fā)到端口8443去 其它屬性略 -->
<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
port="8080"
minProcessors="5" maxProcessors="75" acceptCount="100"
enableLookups="true" redirectPort="8443"
debug="0" connectionTimeout="20000"
useURIValidationHack="false" disableUploadTimeout="true" />
<!-- Engine用來(lái)處理Connector收到的Http請(qǐng)求
它將匹配請(qǐng)求和自己的虛擬主機(jī),并把請(qǐng)求轉(zhuǎn)交給對(duì)應(yīng)的Host來(lái)處理
默認(rèn)虛擬主機(jī)是localhost -->
<Engine name="Standalone" defaultHost="localhost" debug="0">
<!-- 日志類,目前沒(méi)有看到,略去先 -->
<Logger className="org.apache.catalina.logger.FileLogger" .../>
<!-- Realm,目前沒(méi)有看到,略去先 -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" .../>
<!-- 虛擬主機(jī)localhost appBase : 該虛擬主機(jī)的根目錄是webapps/
它將匹配請(qǐng)求和自己的Context的路徑,并把請(qǐng)求轉(zhuǎn)交給對(duì)應(yīng)的Context來(lái)處理 -->
<Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true">
<!-- 日志類,目前沒(méi)有看到,略去先 -->
<Logger className="org.apache.catalina.logger.FileLogger" .../>
<!-- Context,對(duì)應(yīng)于一個(gè)Web App
path : 該Context的路徑名是"",故該Context是該Host的默認(rèn)Context
docBase : 該Context的根目錄是webapps/mycontext/ -->
<Context path="" docBase="mycontext" debug="0"/>
<!-- 另外一個(gè)Context,路徑名是/wsota -->
<Context path="/wsota" docBase="wsotaProject" debug="0"/>
</Host>
</Engine>
</Service>
</Server>
<!--------------------------------------------------------------->