從大學開始接觸java web的開發時就開始使用tomcat部署web項目,對它的理解僅僅停留在"這是個開源免費的servlet容器"的階段,後來也接觸了一些tomcat的體系,原理等方面的知識,也是半知半解,最近又開始看這方面的東西,截止到寫這篇博文,我也不沒有徹底理解它,但一些比較基礎的東西總算有些眉目了,讀源碼不易,且行且珍惜,這裏寫篇筆記整理下.html
先盜張圖:java
能夠看到,Tomcat有一個最頂層的容器,也就是server容器,它最大,在server容器中,能夠有多個service,由service來提供服務,因此service不能沒有,至少得有一個.web
在service中,主要包含兩個組件,Connector和Container.Container上圖中沒有標出,其實就是包含了Engine的部分.apache
Tomcat能夠提供多種協議的請求,http協議就是其中一種,這裏以http請求爲例,一個http請求發到服務器時,由Connector來接收並進行轉換,Connector就是用來處理鏈接相關工做的組件,好比能夠進行Socket與request,response之間的轉換,container是一個包含了servlet等衆多資源的庫,它接受Connector傳過來的request請求,解析出請求的資源,返回給Container,因此Connector和Container一個主外一個主內,兩人共同創建起美滿的家庭.瀏覽器
固然上述比喻是不嚴謹的,由於一個Service中只有一個Container,但卻能夠有多個Connector,下面一段代碼來自Tomcat目錄下conf下的server.xml:tomcat
<Service name="Catalina"> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> </Service>
能夠看到,默認的Tomcat服務配置文件有兩個Connector,一個負責監聽8080端口,一個負責監聽8009端口,前者咱們很熟悉了,它用來監聽來自於瀏覽器的http請求,而後會new出一個線程來把請求傳給Engine,然後者則是用來監聽其餘類型的servlet/jsp請求,叫AJP協議(我也沒據說過).服務器
繼續盜圖,Container的體系結構:網絡
Container是tomcat中容器的接口,咱們最熟悉的Servlet就封裝在Container的子接口Wrapper中.看一下Server.xml中的配置:mvc
<Service name="Catalina"> <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>
Container有四個子容器,根據圖示以及xml配置就能夠看出來他們是逐層包含的關係.app
每一個service中只有一個Engine,Engine中能夠由多個Host,每一個Host能夠有多個Context,每一個Context中能夠有多個Wrapper,而每個Wrapper裏面就封裝着一個Servlet.
下面分別簡單總結幾個容器:
Engine:顧名思義,引擎,它用來管理多個站點,也就是Host.
Host:表示一個站點,也能夠叫作虛擬主機,在上面xml配置中,能夠看到Tomcat默認配置了一個名爲localhost的虛擬主機,咱們部署,運行項目時,就默認進入這個站點,Tomcat回去webapps目錄下去定位請求的web項目資源.
Context:意思是上下文,它表示一個應用程序,也就是咱們開發的一個web項目,一個web項目就能夠理解爲一個Context.
Wrapper:每一個Wrapper封裝一個servlet.
默認配置下的webapps下的每一目錄都是一個應用,其中有一個ROOT目錄表明主應用,整個webapps表示一個站點(Host),當咱們檢測tomcat是否啓動成功時通常都會打開http://localhost:8080/,這時候若是出現tomcat的官方站點就表示啓動成功,其實這時候訪問的就是ROOT應用下的資源,主應用就是直接使用域名訪問就能夠,假設webapps下還有一個helloword目錄,若是你想訪問helloword目錄下的資源,就須要輸入http://localhost:8080/helloword/.
<Server port="8005" shutdown="SHUTDOWN"> <Service name="Catalina"> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" 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>
在server.xml 中首先配置了一個server,在8005端口監聽關閉命令"shutdown".
Server裏定義了一個名爲Catania的Service,Service裏定義了兩個Connector,一個是HTTP協議,一個是AJP協議,此外還定義了一個名爲Catalina的Engine,Engine裏定義了一個名爲localhost的Host.
Host中name屬性表示域名,因此這個默認Host能夠用localhost來訪問,appBase屬性指定了站點的位置,這裏就是webapps目錄,這裏還有不少屬性,詳細介紹,能夠參考這篇博文:http://www.blogjava.net/baoyaer/articles/107278.html
沒盜到圖,本身畫一張:
Connector是用來接收請求並把請求封裝成Request和Response來進行具體的業務處理的,底層使用的Socket鏈接.
Connector實現了TCP/IP協議和HTTP協議,他會把Request和Response按照HTTP協議來進行封裝,封裝完以後交給Container來進行處理,待Container處理完以後,再返回回來,Connector使用Socket將返回結果返回給瀏覽器,完成整個處理請求.
下面簡單介紹Connector中的幾個重要組件
ProtocolHandler:處理不一樣鏈接類型的請求,好比普通Socket請求和NioSocket請求.
Endpoint:處理底層Socket的網絡鏈接.實現的是TCP/IP協議.
Processor:將Endpoint接收到的Socket請求封裝成Request,實現的HTTP協議.
Adapter: 將Request請求適配給Container來處理.
整個Tomcat服務器其實就是java編寫的一個應用,我嘗試着讀了一些源碼,但資歷尚淺,讀的很艱難,一些代碼上的實現方式和原理也不懂,只能大概理解一些類的功能,因此這裏只是簡單總結一些比較膚淺的知識,之後,有決心和毅力再去研讀.共勉.