(精)tomcat 源码学习
Tomcat6是最新版本的web容器,其支持最新版本的servlet2.5和jsp2.1。而且Tomcat6架構也是經(jīng)過重新設計優(yōu)化過的,所以我們有必要分析一下它的架構過程。顯然,這是一個通過閱讀Tomcat的源代碼及相關文檔,演繹架構的過程。或許有人會說,這不是放馬后炮嗎?!!但我覺得這是自我進步的一個必經(jīng)步驟,先模仿之,然后才能超越之,畢竟我本凡人。
Tomcat的架構總的來說是分層次的、可插拔的組件架構。分層次是指構成Tomcat的組件不是同一級別的,上層組件可以包含子組件,各個組件有其功能范圍,當一個組件停止服務時,不會影響上層組件的服務。可插拔是指對于組件的添加和刪除并不影響服務器的運行。那么為了達到可插拔的組件架構,分層次的組件架構必成為基礎。
對于任何服務器,即使最簡單的實現(xiàn),從面向對象設計(OOD)的角度來說,我們都有必要將“服務器”這個概念抽象出來,為什么呢?因為只有有了這個概念,才能談服務器的實例,服務器的功能等等其它概念,此之謂“皮之不存,毛將焉附”。趕巧(其實是我的想法恰好撞上人家的想法),Tomcat也將“服務器”抽象為java接口org.apache.catalina.Server,顯然Server應該就是最最頂層的組件了。
有了Server這個抽象,很自然的,我們希望它能夠提供對servlet和jsp支持的功能。但是我們發(fā)現(xiàn)這個概念太大了,我們還需再細化。所以別急,我們還有一些事情要解決。服務器要提供服務就必須能夠啟動,當然也應該能夠停止吧,也就是說服務器應該是有生命的,在啟動時初始化必要的資源,而在停止時將其其銷毀掉。好吧,我們把這個也抽象出來,叫做生命周期接口,tomcat?實現(xiàn)為org.apache.catalina.Lifecycle.如上所述我們知道Lifecycle需要完成的工作了。
| public?void?start()?throws?LifecycleException; public?void?stop()?throws?LifecycleException; |
接下來我們分析服務器如何來處理客戶端的請求,一般的我們會在瀏覽器中輸入如下格式的請求,http://192.168.8.221:8080/explorer/loginInit.do。對于服務器來說,要想處理這個請求,就必須監(jiān)聽指定的端口8080,當有TCP的請求包來時,建立Socket連接,分析并解析之,然后給客戶端返回響應。在這個過程中,我們發(fā)現(xiàn),其實包含了倆個功能點,即監(jiān)聽并接受請求和處理請求。那么我們能否將這倆個功能給抽象出來呢?Tomcat告訴我們,可以。是的,Tomcat將“監(jiān)聽并接收請求”抽象為org.apache.catalina.connector.Connector類,負責接受請求;將“處理請求”抽象為“容器”org.apache.catalina.Container,負責處理Connector傳遞過來的請求。
Ok,到此,我們分析構建的簡單服務器模型出來了,Server由Connector組件和Container組件結合提供web服務。
圖2
有了這個模型后,要實現(xiàn)一個簡單的Server已經(jīng)很簡單了,但是在實現(xiàn)Container時,我們還是要做很多事情,如當來請求,我們怎么知道該請求對應得虛擬主機,以及請求的那個應用,應該交給那個servlet對象來處理?這樣看來,Container還是太大了,需要細化。根據(jù)Servlet規(guī)范,我們知道,servlet屬于某個應用,且有上下文環(huán)境,Container要根據(jù)應用上下文環(huán)境初始化servlet,然后根據(jù)servlet映射調(diào)用servlet的service方法。在這里“應用上下文環(huán)境”的概念很重要,Tomcat將其抽象為org.apache.catalina.Context,Context繼承了Container接口。對于虛擬主機,Tomcat將其抽象為org.apache.catalina.Host,Host繼承了Container接口。
好了,有了這些概念,我們再回顧一下請求的處理過程:瀏覽器發(fā)出請求,Connector接受請求,將請求交由Container處理,Container查找請求對應的Host并將請求傳遞給它,Host拿到請求后查找相應的應用上下文環(huán)境,準備servlet環(huán)境并調(diào)用service方法。
現(xiàn)在,我們的服務器模型變成了如圖3所示了。
圖3
但是在Tomcat的實現(xiàn)體系中還有一個Engine的接口,Engine也繼承了Container接口,那么這個接口什么用呢?設計Engine的目的有倆個目的,一,當希望使用攔截器查看(過濾或預處理)每個請求時,Engine是個很好的攔截點。二,當希望多個虛擬Host共享一個Http的Connector時,Engine是個很好的門面。所以,Engine接口是作為頂級Container組件來設計的,其作用相當于一個Container的門面。有了Engine,請求的處理過程變?yōu)?#xff1a;瀏覽器發(fā)出請求,Connector接受請求,將請求交由Container(這里是Engine)處理,Container(Engine來擔當)查找請求對應的Host并將請求傳遞給它,Host拿到請求后查找相應的應用上下文環(huán)境,準備servlet環(huán)境并調(diào)用service方法。再看看服務器的模型,如圖4.
圖4
到目前,我們碰到的組件類型有Connector和Container,其實,這也就是Tomcat的核心組件。如圖4,一組Connector和一個Container有機的組合在一起構成Server,就可以提供服務了,對于Tomcat來說,主要是提供Servlet服務,那么也就是說Tomcat服務器也可以提供其它服務了?是的,Tomcat將“一組Connector和一個Container有機的組合”抽象為“服務”接口org.apache.catalina.Service,然而,這些服務實例彼此獨立,僅僅共享JVM的基礎設施,如系統(tǒng)類路徑。
進一步的,我們得到了服務器的框架模型,如圖5.
圖5
????由圖5,我們知道,對于Tomcat服務器來說,除了Server代表它自己以外,其它組件都是功能組件,都有其職責范圍。Service為最頂層的組件,可以添加Connector和Container組件。Engine是Container的最頂層組件,可以添加Host組件,但不能添加父組件。Host組件的父組件是Engine,Host下面包含有Context組件。
????接下來看看標準的Tomcat體系結構,如圖6.
圖6
比較圖5和圖6.我們發(fā)現(xiàn),還有很多輔助組件沒有抽象出來。當然,隨著需求的一步步加深,我的分析也會一步步深入,這些個組件也會慢慢浮出水面。
?
以上轉自:http://blog.163.com/haizai219@126/blog/static/4441255520098841540516/
-------------------------------------------------------------------------------------------------------------------------------------
?
Tomcat從5.5版本開始,支持以下四種Connector的配置分別為 NIO, HTTP, POOL, NIOP:
<Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443"/>
<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>
<Connector executor="tomcatThreadPool"port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Connector executor="tomcatThreadPool" port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" />
?
NetworkClient
? ? ? ? -->Socket-->PlainSocketImpl的native void socketConnect(InetAddress paramInetAddress, int paramInt1, int paramInt2)
?
NetworkServer
? ? ? ? 帶main方法的ServerSocket
?
HttpURLConnection
? ? ? ? -->HttpClient extends NetworkClient
?
?
tomcat 如何通過jmx loader 、digester架構
一、目錄結構:
? ? ? ? apache-tomcat-5.5.23\server\lib
? ? ? ? apache-tomcat-5.5.23\common\lib
? ? ? ? conf\context.xml
? ? ? ? ? ? ? ? <Context><WatchedResource>WEB-INF/web.xml</WatchedResource></Context>
? ? ? ? conf\web.xml
? ? ? ? ? ? ? ? 這個里面的加載 ? ? ? ? ? ? ? ?
? ? ? ? jasper-compiler.jar負責把index_jsp轉化成index_jsp.servlet,(當首次訪問該jsp時)
? ? ? ? ? ? ? ? apache-tomcat-5.5.23\work\Catalina\localhost\myservlet\org\apache\jsp\index_jsp
?
二、
conf\server.xml元素結構
<Server port="8005" shutdown="SHUTDOWN">
? ? ? ? <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener"/>
? ? ? ? <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
? ? ? ? <Service name="Catalina">
? ? ? ? ? ? ? ? //1、端口。將port=80,進入本地服務時就不用敲80在末尾了(瀏覽器默認),這樣當安裝了IIS服務(80端口)時,tomcat無法啟動(它是serversocket)。
? ? ? ? ? ? ? ? <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443" useBodyEncodingForURI="true"/>
? ? ? ? ? ? ? ? <Engine defaultHost="localhost" name="Catalina">
? ? ? ? ? ? ? ? ? ? ? ? <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <Context docBase="mypushlet" path="/mypushlet" reloadable="true" source="org.eclipse.jst.jee.server:mypushlet"/>
? ? ? ? ? ? ? ? ? ? ? ? </Host>
? ? ? ? ? ? ? ? </Engine>
? ? ? ? </Service>
</Server>
2.虛擬目錄:所有的開發(fā)程序【JSP、servlet文件】保存在虛擬目錄中。
? ? ? ? 設虛擬目錄 "myweb",通過 http://localhost:8080/myweb 訪問物理路徑 L:\java\JWeb 文件夾里面的內(nèi)容。設置過程如下:?
? ? ? ? 1.復制 Tomcat6.0\webapps\ROOT 目錄下的 WEB-INF 文件夾到 L:\java\JWeb 目錄下。?
? ? ? ? 2.打開L:\java\JWeb\WEB-INF 目錄下的 web.xml 文件,在 </description> 之后加入:?
? ? ? ? <!--JSPC servlet mappings start -->?
? ? ? ? <!--JSPC servlet mappings end -->?
? ? ? ? 3.打開 Tomcat6.0\conf\server.xml 文件,在 <Host> 和 </Host> 之間加入:?
? ? ? ? <Context path="/myweb" docBase="L:\java\JWeb"></Context>?
? ? ? ? path="/myweb" 就是虛擬目錄的名稱?
? ? ? ? docBase="L:\java\JWeb"> 為物理路徑?
? ? ? ? 4.打開 Tomcat6.0\conf\web.xml 文件,找到:?
? ? ? ? <init-param>?
? ? ? ? <param-name>listings</param-name>?
? ? ? ? <param-value>false</param-value>?
? ? ? ? </init-param>?
? ? ? ? 把false設成true保存,重啟Tomcat,現(xiàn)在就可以應用 http://localhost:8080/myweb 虛擬目錄了。?
? ? ? ? 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是這樣一個集合:它由一個或者多個Connector組成,以及一個Engine,負責處理所有Connector所獲得的客戶請求?
?
? ? ? ? 1.3 - Connector?
? ? ? ? 一個Connector將在某個指定端口上偵聽客戶請求,并將獲得的請求交給Engine來處理,從Engine處獲得回應并返回客戶。?
? ? ? ? Coyote Http/1.1 Connector 在端口8080處偵聽來自客戶browser的http請求?
? ? ? ? Coyote JK2 Connector 在端口8009處偵聽來自其它WebServer(Apache)的servlet/jsp代理請求?
?
? ? ? ? 1.4 - Engine?
? ? ? ? An Engine is a Container that represents the entire Catalina servlet engine.?
? ? ? ? If used, an Engine is always the top level Container in a Catalina.
? ? ? ? Engine下可以配置多個虛擬主機Virtual Host,每個虛擬主機都有一個域名。?
? ? ? ? 當Engine獲得一個請求時,它把該請求匹配到某個Host上,然后把該請求交給該Host來處理
?
? ? ? ? 1.5 - Host?
?
架構:
? ? ? ? Server: 其實就是BackGroud程序, 在Tomcat里面的Server的用處是啟動和監(jiān)聽服務端事件(諸如重啟、關閉等命令。SHUTDOWN)
? ? ? ? Service: 一類問題的解決方案。默認使用Tomcat-Standalone 模式的service。既給我們提供解析jsp和servlet的服務, 同時也提供給我們解析靜態(tài)文本的服務。
?
? ? ? ? Connector:從socket傳遞過來的數(shù)據(jù), 封裝成Request, 傳遞給容器來處理。http、https、ajp(apache與tomcat)三種
? ? ? ? ? ? ? ? Container: 當http connector把需求傳遞給頂級的container: Engin的時候, 我們的視線就應該移動到Container這個層面來了。
? ? ? ? ? ? ? ? 在Container這個層, 我們包含了3種容器: Engin, Host, Context.
? ? ? ? ? ? ? ? Engin: 收到service傳遞過來的需求, 處理后, 將結果返回給service( service 是通過 connector 這個媒介來和Engin互動的 ).
? ? ? ? ? ? ? ? Host: Engin收到service傳遞過來的需求后,不會自己處理, 而是交給合適的Host來處理。
? ? ? ? ? ? ? ? Host在這里就是虛擬主機的意思, 通常我們都只會使用一個主機,既“l(fā)ocalhost”本地機來處理。?
? ? ? ? ? ? ? ? Context: 一個web app,Host接到了從Host傳過來的需求后, 也不會自己處理, 而是交給合適的Context來處理。?
?
? ? ? ? Compenent: 容器有各種各樣的組件, 提供各種各樣的增值服務。
? ? ? ? ? ? ? ? manager: 當一個容器里面裝了manager組件后,這個容器就支持session管理了, 事實上在tomcat里面的session管理, 就是靠的在context里面裝的manager component.
? ? ? ? ? ? ? ? logger: 當一個容器里面裝了logger組件后
? ? ? ? ? ? ? ? loader: 通常只會給我們的context容器使用, loader是用來啟動context以及管理這個context的classloader用的。
? ? ? ? ? ? ? ? pipline: 容器間傳遞并過濾。
2. Tomcat的啟動流程: 第一步是裝配工作(父容器裝上子容器,容器安插進組件)。 第二步是啟動工作。?
?
?
2.3 Catalina.java
? ? ? ? 1. 使用Digester技術裝配tomcat各個容器與組件。
? ? ? ? ? ? ? ? 1.1 裝配工作的主要內(nèi)容是安裝各個大件。 比如server下有什么樣的servcie。 Host會容納多少個context。 Context都會使用到哪些組件等等。?
? ? ? ? ? ? ? ? 1.2 同時呢, 在裝配工作這一步, 還完成了mbeans的配置工作。 在這里,我簡單地但不十分精確地描述一下mbean是什么,干什么用的。
? ? ? ? ? ? ? ? 我們自己生成的對象, 自己管理, 天經(jīng)地義! 但是如果我們創(chuàng)建了對象了, 想讓別人來管, 怎么辦呢? 我想至少得告訴別人我們都有什么, 以及通過什么方法可以找到 吧! JMX技術給我們提供了一種手段。 JMX里面主要有3種東西。Mbean, agent, connector.
? ? ? ? ? ? ? ? Mbean: 用來映射我們的對象。也許mbean就是我們創(chuàng)建的對象, 也許不是, 但有了它, 就可以引用到我們的對象了。
? ? ? ? ? ? ? ? Agent: 通過它, 就可以找到mbean了。
? ? ? ? ? ? ? ? Connector: 連接Agent的方式。 可以是http的, 也可以是rmi的,還可以直接通過socket。
? ? ? ? ? ? ? ? 發(fā)生在tomcat 裝配過程中的事情: GlobalResourcesLifecycleListener 類的初始化會被觸發(fā):
? ? ? ? ? ? ? ? protected static Registry registry = MBeanUtils.createRegistry(); 會運行
? ? ? ? ? ? ? ? MBeanUtils.createRegistry() 會依據(jù)/org/apache/catalina/mbeans/mbeans-descriptors.xml這個配置文件創(chuàng)建 mbeans. Ok, 外界就有了條途徑訪問tomcat中的各個組件了。
? ? ? ? 2. 為top level 的server 做初始化工作。 實際上就是做通常會配置給service的兩條connector.(http, ajp)
? ? ? ? 3. 從server這個容器開始啟動, 點燃整個tomcat.
? ? ? ? 4. 為server做一個hook程序, 檢測當server shutdown的時候, 關閉tomcat的各個容器用。
? ? ? ? 5. 監(jiān)聽8005端口, 如果發(fā)送"SHUTDOWN"(默認培植下字符串)過來, 關閉8005serverSocket。
2.4 啟動各個容器
? ? ? ? 1. Server
? ? ? ? ? ? ? ? 觸發(fā)Server容器啟動前(before_start), 啟動中(start), 啟動后(after_start)3個事件, 并運行相應的事件處理器。
? ? ? ? ? ? ? ? 啟動Server的子容器:Servcie.?
? ? ? ? 2. Service
? ? ? ? ? ? ? ? 啟動Service的子容器:Engin
? ? ? ? ? ? ? ? 啟動Connector
? ? ? ? 3. Engin
? ? ? ? ? ? ? ? 到了Engin這個層次,以及以下級別的容器, Tomcat就使用了比較一致的啟動方式了。
? ? ? ? ? ? ? ? 首先, 運行各個容器自己特有一些任務
? ? ? ? ? ? ? ? 隨后, 觸發(fā)啟動前事件
? ? ? ? ? ? ? ? 立即, 設置標簽,就表示該容器已經(jīng)啟動
? ? ? ? ? ? ? ? 接著, 啟動容器中的各個組件: loader, logger, manager等等
? ? ? ? ? ? ? ? 再接著,啟動mapping組件。(注1)
? ? ? ? ? ? ? ? 緊跟著,啟動子容器。
? ? ? ? ? ? ? ? 接下來,啟動該容器的管道(pipline)
? ? ? ? ? ? ? ? 然后, 觸發(fā)啟動中事件
? ? ? ? ? ? ? ? 最后, 觸發(fā)啟動后事件。
? ? ? ? ? ? ? ? Engin大致會這么做, Host大致也會這么做, Context大致還是會這么做。 那么很顯然地, 我們需要在這里使用到代碼復用的技術。 tomcat在處理這個問題的時候, 漂亮地使用了抽象類來處理。 ContainerBase. 最后使得這部分完成復雜功能的代碼顯得干凈利落, 干練爽快, 實在是令人覺得嘆為觀止, 細細品來, 直覺如享佳珍, 另人齒頰留香, 留戀往返啊!
? ? ? ? ? ? ? ? Engin的觸發(fā)啟動前事件里, 會激活綁定在Engin上的唯一一個Listener:EnginConfig。
? ? ? ? ? ? ? ? 這個EnginConfig類基本上沒有做什么事情, 就是把EnginConfig的調(diào)試級別設置為和Engin相當。 另外就是輸出幾行文本, 表示Engin已經(jīng)配置完畢, 并沒有做什么實質性的工作。
? ? ? ? ? ? ? ? 注1: mapping組件的用處是, 當一個需求將要從父容器傳遞到子容器的時候, 而父容器又有多個子容器的話, 那么應該選擇哪個子容器來處理需求呢? 這個由mapping 組件來定奪。
? ? ? ? 4. Host
? ? ? ? ? ? ? ? 同Engin一樣, 也是調(diào)用ContainerBase里面的start()方法, 不過之前做了些自個兒的任務,就是往Host這個容器的通道(pipline)里面, 安裝了一個叫做
? ? ? ? ? ? ? ? “org.apache.catalina.valves.ErrorReportValve”的閥門。
? ? ? ? ? ? ? ? 這個閥門的用處是這樣的: 需求在被Engin傳遞給Host后, 會繼續(xù)傳遞給Context做具體的處理。 這里需求其實就是作為參數(shù)傳遞的Request, Response。 所以在context把需求處理完后, 通常會改動response。 而這個org.apache.catalina.valves.ErrorReportValve的作用就是檢察response是否包含錯誤, 如果有就做相應的處理。
? ? ? ? 5. Context
? ? ? ? ? ? ? ? 到了這里, 就終于輪到了tomcat啟動中真正的重頭戲,啟動Context了。
? ? ? ? ? ? ? ? StandardContext.start() 這個啟動Context容器的方法被StandardHost調(diào)用.
? ? ? ? ? ? ? ? 5.1 webappResources 該context所指向的具體目錄
? ? ? ? ? ? ? ? 5.2 安裝defaultContex, DefaultContext 就是默認Context。 如果我們在一個Host下面安裝了DefaultContext,而且defaultContext里面又安裝了一個數(shù)據(jù)庫連接池資源的話。 那么其他所有的在該Host下的Context, 都可以直接使用這個數(shù)據(jù)庫連接池, 而不用格外做配置了。
? ? ? ? ? ? ? ? 5.3 指定Loader. 通常用默認的org.apache.catalina.loader.WebappLoader這個類。 ? Loader就是用來指定這個context會用到哪些類啊, 哪些jar包啊這些什么的。
? ? ? ? ? ? ? ? 5.4 指定 Manager. 通常使用默認的org.apache.catalina.session. StandardManager 。 Manager是用來管理session的。
? ? ? ? ? ? ? ? 其實session的管理也很好實現(xiàn)。 以一種簡單的session管理為例。 當需求傳遞過來的時候, 在Request對象里面有一個sessionId 屬性。 OK, 得到這個sessionId后, 我們就可以把它作為map的key,而value我們可以放置一個HashMap. HashMap里邊兒, 再放我們想放的東西。
? ? ? ? ? ? ? ? 5.5 postWorkDirectory (). Tomcat下面有一個work目錄。 我們把臨時文件都扔在那兒去。 這個步驟就是在那里創(chuàng)建一個目錄。 一般說來會在%CATALINA_HOME%/work/Standalone\localhost\ 這個地方生成一個目錄。
? ? ? ? ? ? ? ? 5.6 Binding thread。到了這里, 就應該發(fā)生 class Loader 互換了。 之前是看得見tomcat下面所有的class和lib. 接下來需要看得見當前context下的class。 所以要設置contextClassLoader, 同時還要把舊的ClassLoader記錄下來,因為以后還要用的。
? ? ? ? ? ? ? ? 5.7 啟動 Loader. 指定這個Context具體要使用哪些classes, 用到哪些jar文件。 如果reloadable設置成了true, 就會啟動一個線程來監(jiān)視classes的變化, 如果有變化就重新啟動Context。
? ? ? ? ? ? ? ? 5.8 啟動logger
? ? ? ? ? ? ? ? 5.9 觸發(fā)安裝在它身上的一個監(jiān)聽器。
? ? ? ? ? ? ? ? lifecycle.fireLifecycleEvent(START_EVENT, null);?
? ? ? ? ? ? ? ? 作為監(jiān)聽器之一,ContextConfig會被啟動. ContextConfig就是用來配置web.xml的。 比如這個Context有多少Servlet, 又有多少Filter, 就是在這里給Context裝上去的。
? ? ? ? ? ? ? ? 5.9.1 defaultConfig. 每個context都得配置 tomcat/conf/web.xml 這個文件。
? ? ? ? ? ? ? ? 5.9.2 applicationConfig 配置自己的 WEB-INF/web.xml 文件
? ? ? ? ? ? ? ? 5.9.3 validateSecurityRoles 權限驗證。 通常我們在訪問/admin 或者/manager的時候,需要用戶要么是admin的要么是manager的, 才能訪問。 而且我們還可以限制那些資源可以訪問, 而哪些不能。 都是在這里實現(xiàn)的。
? ? ? ? ? ? ? ? 5.9.4 tldScan: 掃描一下, 需要用到哪些標簽(tag lab)
? ? ? ? ? ? ? ? 5.10 啟動 manager
? ? ? ? ? ? ? ? 5.11 postWelcomeFiles() 我們通常會用到的3個啟動文件的名稱:
? ? ? ? ? ? ? ? index.html、index.htm、index.jsp 就被默認地綁在了這個context上
? ? ? ? ? ? ? ? 5.12 listenerStart 配置listener
? ? ? ? ? ? ? ? 5.13 filterStart 配置 filter
? ? ? ? ? ? ? ? 5.14 啟動帶有<load-on-startup>1</load-on-startup>的Servlet.
? ? ? ? ? ? ? ? 順序是從小到大: 1,2,3… 最后是0
? ? ? ? ? ? ? ? 默認情況下, 至少會啟動如下3個的Servlet:?
? ? ? ? ? ? ? ? org.apache.catalina.servlets.DefaultServlet ??
? ? ? ? ? ? ? ? 處理靜態(tài)資源的Servlet. 什么圖片啊, html啊, css啊, js啊都找他
? ? ? ? ? ? ? ? org.apache.catalina.servlets.InvokerServlet
? ? ? ? ? ? ? ? 處理沒有做Servlet Mapping的那些Servlet.
? ? ? ? ? ? ? ? org.apache.jasper.servlet.JspServlet?
? ? ? ? ? ? ? ? 處理JSP文件的.
? ? ? ? ? ? ? ? 5.15 標識context已經(jīng)啟動完畢,tomcat啟動完畢。
?
?
/**
?* A <b>Host</b> is a Container that represents a virtual host in the
?* Catalina servlet engine. ?It is useful in the following types of scenarios:
?* <ul>
?* <li>You wish to use Interceptors that see every single request processed
?* ? ? by this particular virtual host.
?* <li>You wish to run Catalina in with a standalone HTTP connector, but still
?* ? ? want support for multiple virtual hosts.
?* </ul>
?* In general, you would not use a Host when deploying Catalina connected
?* to a web server (such as Apache), because the Connector will have
?* utilized the web server's facilities to determine which Context (or
?* perhaps even which Wrapper) should be utilized to process this request.
?* <p>
?* The parent Container attached to a Host is generally an Engine, but may
?* be some other implementation, or may be omitted if it is not necessary.
?* <p>
?* The child containers attached to a Host are generally implementations
?* of Context (representing an individual servlet context).
?*/ ? ? ? ?
? ? ? ? 每個虛擬主機下都可以部署(deploy)一個或者多個Web App,每個Web App對應于一個Context,有一個Context path。?
? ? ? ? 當Host獲得一個請求時,將把該請求匹配到某個Context上,然后把該請求交給該Context來處理。
?
? ? ? ? 1.6 - Context?
? ? ? ? 一個Context對應于一個Web Application,一個Web Application由一個或者多個Servlet組成。
? ? ? ? Context在創(chuàng)建的時候將根據(jù)配置文件$CATALINA_HOME/conf/web.xml和$WEBAPP_HOME/WEB-INF/web.xml載入Servlet類。
? ? ? ? 當Context獲得請求時,將在自己的映射表(mapping table)中尋找相匹配的Servlet類,如果找到,則執(zhí)行該類,獲得請求的回應,并返回。?
?
? ? ? ? 1.7 - 示例
? ? ? ? browser發(fā)送請求到本機端口8080--> Connector --> Engine --> Host --> Context --> servlet 構造request、response --> Context --> Host --> Engine -- > connector --> browser
?
?
public final class Bootstrap{
? ? ? ? private static Bootstrap daemon = null;
? ? ? ? private Object catalinaDaemon;
? ? ? ? protected ClassLoader commonLoader;
? ? ? ? protected ClassLoader catalinaLoader;
? ? ? ? protected ClassLoader sharedLoader;//Webapp1Loader ?Webapp2Loader ...?
?
? ? ? ? public Bootstrap(){...}
? ? ? ? private void initClassLoaders(){...}
? ? ? ? catalinaDaemon = this.catalinaLoader.loadClass("org.apache.catalina.startup.Catalina").newInstance();
?
? ? ? ? public void start()throws Exception{
? ? ? ? ? ? ? ? Method method = this.catalinaDaemon.getClass().getMethod("start", (Class[])null);
? ? ? ? ? ? ? ? method.invoke(this.catalinaDaemon, (Object[])null);
? ? ? ? }
}
?
public class StandardService implements Lifecycle, Service, MBeanRegistration?
? ? protected Connector connectors[] = new Connector[0];
? ? protected ArrayList<Executor> executors = new ArrayList<Executor>();
? ? /**?
? ? ?* this holds the most recently added Engine.is generally an instance of Engine
? ? ?*/
? ? protected Container container = null;
? ? ? ? /**
? ? ?* The lifecycle event support for this component.
? ? ?*/
? ? private LifecycleSupport lifecycle = new LifecycleSupport(this);
? ? /**
? ? ?* The <code>Server</code> that owns this Service, if any.
? ? ?*/
? ? private Server server = null;
? ? /**
? ? ?* The property change support for this component.
? ? ?*/
? ? protected PropertyChangeSupport support = new PropertyChangeSupport(this);
? ? public void addConnector(Connector connector) {}
? ? ? ? public void addPropertyChangeListener(PropertyChangeListener listener) {}
? ? ? ? public void addExecutor(Executor ex) {}
? ? ? ? public void addLifecycleListener(LifecycleListener listener) {}
}
?
//embed [im'bed] 嵌入
public class Embedded ?extends StandardServic{
? ? ? ? public synchronized void addEngine(Engine engine) {}
}
//啟動Tomcat,就生成Catalina實例,server實例????
根據(jù)配置文件server.xml,實例化的對象。對象實例化過程中,會做載入webapp,在特定端口等待客戶連接等工作。?
從server.xml到對象的映射是通過commons-digester.jar包完成的。這個包的一個主要功能就是映射xml到java對象。
public class Catalina extends Embedded {
? ? protected String configFile = "conf/server.xml";
? ? /**
? ? ?* The application main program.
? ? ?* @param args Command line arguments
? ? ?*/
? ? public static void main(String args[]) {
? ? ? ? (new Catalina()).process(args);
? ? }
? ? /**
? ? ?* The instance main program.
? ? ?* @param args Command line arguments
? ? ?*/
? ? public void process(String args[]) {
? ? ? ? load(args);
? ? ? ? start();
? ? }
? ? /**
? ? ?* Start a new server instance.
? ? ?*/
? ? public void start() {
? ? ? ? ? ? ? ? ((Lifecycle) getServer()).start();
? ? }
? ? ? ? protected Digester createStartDigester() {
? ? ? ? digester.addObjectCreate("Server",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"org.apache.catalina.core.StandardServer",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"className");
? ? ? ? digester.addSetProperties("Server");
? ? ? ? digester.addSetNext("Server",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "setServer",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.Server");
?
? ? ? ? digester.addSetNext("Server/GlobalNamingResources",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "setGlobalNamingResources",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.deploy.NamingResources");
?
? ? ? ? digester.addSetNext("Server/Listener",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "addLifecycleListener",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.LifecycleListener");
?
? ? ? ? digester.addSetNext("Server/Service",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "addService",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.Service");
?
? ? ? ? digester.addSetNext("Server/Service/Listener",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "addLifecycleListener",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.LifecycleListener");
?
? ? ? ? digester.addSetNext("Server/Service/Executor",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "addExecutor",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.Executor");
?
? ? ? ? digester.addSetNext("Server/Service/Connector",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "addConnector",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.connector.Connector");
?
? ? ? ? digester.addSetNext("Server/Service/Connector/Listener",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "addLifecycleListener",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "org.apache.catalina.LifecycleListener");
? ? }
}
?
//available for use(but not required) when deploying and starting Catalina. ? ? ? ?
public final class StandardServer implements Lifecycle, Server, MBeanRegistration{?
? ? public StandardServer() {
? ? ? ? ServerFactory.setServer(this);
? ? ? ? globalNamingResources = new NamingResources();
? ? ? ? globalNamingResources.setContainer(this);
? ? ? ? if (isUseNaming()) {
? ? ? ? ? ? if (namingContextListener == null) {
? ? ? ? ? ? ? ? namingContextListener = new NamingContextListener();
? ? ? ? ? ? ? ? addLifecycleListener(namingContextListener);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? private javax.naming.Context globalNamingContext = null;
? ? private NamingResources globalNamingResources = null;
? ? private NamingContextListener namingContextListener = null;
? ? /**
? ? ?* The port number on which we wait for shutdown commands.
? ? ?*/
? ? private int port = 8005;
? ? awaitSocket = new ServerSocket(port, 1, InetAddress.getByName("localhost"));
} ? ? ? ?
?
?
public class Connector implements Lifecycle, MBeanRegistration{
? ? protected Service service = null;
? ? /**
? ? ?* The Container used for processing requests received by this Connector.
? ? ?*/
? ? protected Container container = null;
? ? /**
? ? ?* Use "/" as path for session cookies ?
? ? ?*/
? ? protected boolean emptySessionPath = false;
? ? ? ? /**
? ? ?* The redirect port for non-SSL to SSL redirects.
? ? ?*/
? ? protected int redirectPort = 443;
? ? /**
? ? ?* The request scheme that will be set on all requests received through this connector.
? ? ?*/
? ? protected String scheme = "http";
? ? /**
? ? ?* Maximum size of a POST which will be automatically parsed by the
? ? ?* container. 2MB by default.
? ? ?*/
? ? protected int maxPostSize = 2 * 1024 * 1024;
? ? /**
? ? ?* Maximum size of a POST which will be saved by the container
? ? ?* during authentication可信的. 4kB by default
? ? ?*/
? ? protected int maxSavePostSize = 4 * 1024;
? ? /**
? ? ?* The background thread.
? ? ?*/
? ? protected Thread thread = null;
? ? /**
? ? ?* Coyote Protocol handler class name.
? ? ?* Defaults to the Coyote HTTP/1.1 protocolHandler.
? ? ?*/
? ? protected String protocolHandlerClassName =
? ? ? ? "org.apache.coyote.http11.Http11Protocol";
? ? /**
? ? ?* Coyote protocol handler.
? ? ?*/
? ? protected ProtocolHandler protocolHandler = null;
? ? /**
? ? ?* Coyote adapter.
? ? ?*/
? ? protected Adapter adapter = null;
? ? ?/**
? ? ? * Mapper.
? ? ? */
? ? ?protected Mapper mapper = new Mapper();
? ? ?/**
? ? ? * Mapper listener.
? ? ? */
? ? ?protected MapperListener mapperListener = new MapperListener(mapper, this);
? ? ?/**
? ? ? * URI encoding.
? ? ? */
? ? ?protected String URIEncoding = null;
? ? ?/**
? ? ? * URI encoding as body.
? ? ? */
? ? protected boolean useBodyEncodingForURI = false;
? ? /**
? ? ?* Set the Coyote protocol which will be used by the connector.
? ? ?*/
? ? public void setProtocol(String protocol) {
? ? ? ? if (AprLifecycleListener.isAprAvailable()) {
? ? ? ? ? ? if ("HTTP/1.1".equals(protocol)) {
? ? ? ? ? ? ? ? setProtocolHandlerClassName
? ? ? ? ? ? ? ? ? ? ("org.apache.coyote.http11.Http11AprProtocol");
? ? ? ? ? ? } else if ("AJP/1.3".equals(protocol)) {
? ? ? ? ? ? ? ? setProtocolHandlerClassName
? ? ? ? ? ? ? ? ? ? ("org.apache.coyote.ajp.AjpAprProtocol");
? ? ? ? ? ? } else if (protocol != null) {
? ? ? ? ? ? ? ? setProtocolHandlerClassName(protocol);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? setProtocolHandlerClassName
? ? ? ? ? ? ? ? ? ? ("org.apache.coyote.http11.Http11AprProtocol");
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? if ("HTTP/1.1".equals(protocol)) {
? ? ? ? ? ? ? ? setProtocolHandlerClassName
? ? ? ? ? ? ? ? ? ? ("org.apache.coyote.http11.Http11Protocol");
? ? ? ? ? ? } else if ("AJP/1.3".equals(protocol)) {
? ? ? ? ? ? ? ? setProtocolHandlerClassName
? ? ? ? ? ? ? ? ? ? ("org.apache.jk.server.JkCoyoteHandler");
? ? ? ? ? ? } else if (protocol != null) {
? ? ? ? ? ? ? ? setProtocolHandlerClassName(protocol);
? ? ? ? ? ? }
? ? ? ? }
? ? }
?
? ? /**
? ? ?* Create (or allocate) and return a Request object suitable for
? ? ?* specifying the contents of a Request to the responsible Container.
? ? ?org.apache.catalina.connector.Request
? ? ?*/
? ? public Request createRequest() {
? ? ? ? Request request = new Request();
? ? ? ? request.setConnector(this);
? ? ? ? return (request);
? ? }
? ? /**
? ? ?* Create (or allocate) and return a Response object suitable for
? ? ?* receiving the contents of a Response from the responsible Container.
? ? ?*/
? ? public Response createResponse() {
? ? ? ? Response response = new Response();
? ? ? ? response.setConnector(this);
? ? ? ? return (response);
? ? }
? ? // 省略------------------------------------------------------ Lifecycle Methods
? ? // 省略-------------------- JMX registration ?--------------------
? ? /**
? ? ?* Shutdown hook which will perform a clean shutdown of Catalina if needed.
? ? ?*/
? ? protected class CatalinaShutdownHook extends Thread {
? ? ? ? public void run() {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? if (getServer() != null) {
? ? ? ? ? ? ? ? ? ? Catalina.this.stop();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } catch (Throwable ex) {
? ? ? ? ? ? ? ? log.error(sm.getString("catalina.shutdownHookFail"), ex);
? ? ? ? ? ? } finally {
? ? ? ? ? ? ? ? // If JULI is used, shut JULI down *after* the server shuts down
? ? ? ? ? ? ? ? // so log messages aren't lost
? ? ? ? ? ? ? ? LogManager logManager = LogManager.getLogManager();
? ? ? ? ? ? ? ? if (logManager instanceof ClassLoaderLogManager) {
? ? ? ? ? ? ? ? ? ? ((ClassLoaderLogManager) logManager).shutdown();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
} ? ? ? ??
?
public interface Engine extends Container {
? ? public String getDefaultHost();
? ? public void setDefaultHost(String defaultHost);
? ? public String getJvmRoute();
? ? public void setJvmRoute(String jvmRouteId);
? ? public Service getService();
? ? public void setService(Service service);
} ? ? ? ?
public class StandardEngine extends ContainerBase implements Engine{} ? ? ? ?
?
?
public class StandardHost extends ContainerBase implements Host{
? ? ? ? /**
? ? ?* The set of aliases for this Host.
? ? ?*/
? ? ? ? private String[] aliases = new String[0];
? ? private final Object aliasesLock = new Object();
? ? /**
? ? ?* The application root for this Host.
? ? ?*/
? ? private String appBase = "webapps";
? ? /**
? ? ?* The auto deploy flag for this Host.
? ? ?*/
? ? private boolean autoDeploy = true;
? ? /**
? ? ?* The Java class name of the default context configuration class
? ? ?* for deployed web applications.
? ? ?*/
? ? private String configClass =
? ? ? ? "org.apache.catalina.startup.ContextConfig";
? ? /**
? ? ?* The Java class name of the default Context implementation class for
? ? ?* deployed web applications.
? ? ?*/
? ? private String contextClass =
? ? ? ? "org.apache.catalina.core.StandardContext";
? ? /**
? ? ?* Attribute value used to turn on/off XML namespace awarenes.
? ? ?*/
? ? ?private boolean xmlNamespaceAware = false;
? ? ?/**
? ? ? * Track the class loaders for the child web applications so memory leaks漏洞
? ? ? * can be detected.
? ? ? */
? ? ?private Map<ClassLoader, String> childClassLoaders =
? ? ? ? ?new WeakHashMap<ClassLoader, String>();
? ? ?...其他的field省略
} ? ? ? ??
?
/**
?* Standard implementation of the <b>Context</b> interface. ?Each
?* child container must be a Wrapper implementation to process the
?* requests directed to a particular servlet.
?*/
public class StandardContext extends ContainerBase implements Context, Serializable, NotificationEmitter{ ? ? ? ?
? ? ? ? /**
? ? ?* The ServletContext implementation associated with this Context.
? ? ?*/
? ? protected transient ApplicationContext context = null;
? ? /**
? ? ?* Compiler classpath to use.
? ? ?*/
? ? private String compilerClasspath = null;
? ? ?/**
? ? ?* Should we attempt to use cookies for session id communication?
? ? ?*/
? ? private boolean cookies = true;
? ? /**
? ? ?* Should we allow the <code>ServletContext.getContext()</code> method
? ? ?* to access the context of other web applications in this server?
? ? ?*/
? ? private boolean crossContext = false;
? ? /**
? ? ?* The MIME mappings for this web application, keyed by extension.
? ? ?*/
? ? private HashMap mimeMappings = new HashMap();
? ? /**
? ? ?* The servlet mappings for this web application, keyed by
? ? ?* matching pattern.
? ? ?*/
? ? private HashMap servletMappings = new HashMap();
? ? /**
? ? ?* The welcome files for this application.
? ? ?*/
? ? private String welcomeFiles[] = new String[0];
? ? /**
? ? ?* Cache object max size in KB.
? ? ?*/
? ? protected int cacheObjectMaxSize = 512; // 512K
? ? /**
? ? ?* Cache TTL in ms.
? ? ?*/
? ? protected int cacheTTL = 5000;
? ? ?/**
? ? ?* The domain to use for session cookies. <code>null</code> indicates that
? ? ?* the domain is controlled by the application.
? ? ?*/
? ? private String sessionCookieDomain;
? ? /**
? ? ?* The path to use for session cookies. <code>null</code> indicates that
? ? ?* the path is controlled by the application.
? ? ?*/
? ? private String sessionCookiePath;
? ? /**
? ? ?* The name to use for session cookies. <code>null</code> indicates that
? ? ?* the name is controlled by the application.
? ? ?*/
? ? private String sessionCookieName;
} ? ? ? ? ? ?
?
/**
?* Standard implementation of the <b>Wrapper</b> interface that represents
?* an individual servlet definition. ?No child Containers are allowed, and
?* the parent Container must be a Context.
?*/
public interface Wrapper extends Container{}?
public class StandardWrapper extends ContainerBase implemen ts ServletConfig, Wrapper, NotificationEmitter {
? ? ? ? /**
? ? ?* The (single) initialized instance of this servlet.
? ? ?*/
? ? protected Servlet instance = null;
? ? /**
? ? ?* The context-relative URI of the JSP file for this servlet.
? ? ?*/
? ? protected String jspFile = null;
} ? ? ? ?
?
/**
?* Standard implementation of <code>ServletContext</code> that represents
?* a web application's execution environment. ?An instance of this class is
?* associated with each instance of <code>StandardContext</code>.
?*/
public class ApplicationContext implements ServletContext {
? ? /**
? ? ?* The Context instance with which we are associated.
? ? ?*/
? ? private StandardContext context = null;
? ? ? ? /**
? ? ?* Base path.
? ? ?*/
? ? private String basePath = null;
? ? ? ? public String getRealPath(String path) {
? ? ? ? ? ? ? ? File file = new File(basePath, path);
? ? ? ? return (file.getAbsolutePath());
? ? ? ? }
? ? /**
? ? ?* Return a <code>RequestDispatcher</code> instance that acts as a
? ? ?* wrapper for the resource at the given path. ?The path must begin
? ? ?* with a "/" and is interpreted as relative to the current context root.
? ? ?*
? ? ?* @param path The path to the desired resource.
? ? ?*/
? ? public RequestDispatcher getRequestDispatcher(String path) {}
? ? protected StandardContext getContext() {
? ? ? ? return this.context;
? ? }
} ? ? ? ?
?
/**
?* Startup event listener for a <b>Context</b> that configures the properties
?* of that Context, and the associated defined servlets.
?*/
public class ContextConfig implements LifecycleListener {
? ? /**
? ? ?* The Context we are associated with.
? ? ?*/
? ? protected Context context = null;
? ? /**
? ? ?* The default web application's context file location.
? ? ?*/
? ? protected String defaultContextXml = null;
? ? /**
? ? ?* The default web application's deployment descriptor location.
? ? ?*/
? ? protected String defaultWebXml = null;
} ? ? ? ?
?
?
org.apache.catalina.core.ApplicationHttpRequest?
? ? ? ? extends javax.servlet.http.HttpServletRequestWrapper?
? ? ? ? extends javax.servlet.ServletRequestWrapper
?
//作用類似javaBean
public final class org.apache.coyote.Request{
? ? ? ? private int serverPort = -1;
? ? ? ? private UDecoder urlDecoder = new UDecoder();
? ? ? ? private MimeHeaders headers = new MimeHeaders();
? ? ? ? private MessageBytes uriMB = MessageBytes.newInstance(); ? ? ? ?
}
org.apache.catalina.connector.Request implements HttpServletRequest{
? ? ? ? protected org.apache.coyote.Request coyoteRequest
? ? ? ? public InputStream getStream() {
? ? ? ? if (inputStream == null) {
? ? ? ? ? ? inputStream = new CoyoteInputStream(inputBuffer);
? ? ? ? }
? ? ? ? return inputStream;
? ? }
? ? ? ? protected int readPostBody(byte body[], int len)throws IOException {
? ? ? ? ? ? ? ? int inputLen = getStream().read(body, offset, len - offset);
? ? ? ? }
? ? ? ? /**
? ? ?* Return the session associated with this Request, creating one
? ? ?* if necessary and requested.
? ? ?*/
? ? public HttpSession getSession(boolean create) {
? ? ? ? Session session = doGetSession(create);
? ? ? ? if (session != null) {
? ? ? ? ? ? return session.getSession();
? ? ? ? } else {
? ? ? ? ? ? return null;
? ? ? ? }
? ? }
? ? ? ? /**
? ? ?* Change the ID of the session that this request is associated with. There
? ? ?* are several things that may trigger an ID change. These include moving
? ? ?* between nodes in a cluster and session fixation prevention during the
? ? ?* authentication process.
? ? ?*/
? ? public void changeSessionId(String newSessionId) {...}
? ? protected Session doGetSession(boolean create) {
? ? ? ? // Attempt to reuse session id if one was submitted in a cookie
? ? ? ? // Do not reuse the session id if it is from a URL, to prevent possible
? ? ? ? // phishing attacks
? ? ? ? if (connector.getEmptySessionPath()?
? ? ? ? ? ? ? ? && isRequestedSessionIdFromCookie()) {
? ? ? ? ? ? session = manager.createSession(getRequestedSessionId());
? ? ? ? } else {
? ? ? ? ? ? ? ? //createSession最終會調(diào)用StandardSession的構造。
? ? ? ? ? ? session = manager.createSession(null);
? ? ? ? }
? ? ? ? // Creating a new session cookie based on that session
? ? ? ? if ((session != null) && (getContext() != null)
? ? ? ? ? ? ? ?&& getContext().getCookies()) {
? ? ? ? ? ? String scName = context.getSessionCookieName();
? ? ? ? ? ? if (scName == null) {
? ? ? ? ? ? ? ? scName = Globals.SESSION_COOKIE_NAME;
? ? ? ? ? ? }
? ? ? ? ? ? Cookie cookie = new Cookie(scName, session.getIdInternal());
? ? ? ? ? ? configureSessionCookie(cookie);
? ? ? ? ? ? //save到瀏覽器內(nèi)存
? ? ? ? ? ? response.addSessionCookieInternal(cookie, context.getUseHttpOnly());
? ? ? ? }
? ? }
? ? ?/**
? ? ?* Parse accept-language header value.
? ? ?*/
? ? protected void parseLocalesHeader(String value) {...}
? ? public String getParameter(String name) {...}
}
?
Connector通過8080端口連接coyote http1.1,通過8009連接coyote AJP1.3
?
ServerCookie、Cookies與javax.servlet.http.Cookie的聯(lián)系?
cookie如何實現(xiàn)的?還有瀏覽器的。如何獲取解析cookie、url重寫過的sessionid ? ? ?
/**
?* ?Server-side cookie representation.
?* ?Allows recycling and uses MessageBytes as low-level
?* ?representation ( and thus the byte-> char conversion can be delayed
?* ?until we know the charset ).
?* ?Tomcat.core uses this recyclable object to represent cookies,
?* ?and the facade will convert it to the external representation.
?*/
public class org.apache.tomcat.util.http.ServerCookie implements Serializable {...} ? ? ? ?
?
/**
?* A collection of cookies - reusable and tuned for server side performance.
?* Based on RFC2965 ( and 2109 )
?*/
public final class org.apache.tomcat.util.http.Cookies {?
? ? ServerCookie scookies[]=new ServerCookie[INITIAL_SIZE];
? ? /** Register a new, unitialized cookie. Cookies are recycled, and
? ? ?* ?most of the time an existing ServerCookie object is returned.
? ? ?* ?The caller can set the name/value and attributes for the cookie
? ? ?*/
? ? public ServerCookie addCookie() {
? ? ? ? if( cookieCount >= scookies.length ?) {
? ? ? ? ? ? ServerCookie scookiesTmp[]=new ServerCookie[2*cookieCount];
? ? ? ? ? ? System.arraycopy( scookies, 0, scookiesTmp, 0, cookieCount);
? ? ? ? ? ? scookies=scookiesTmp;
? ? ? ? }
? ? ? ? ServerCookie c = scookies[cookieCount];
? ? ? ? if( c==null ) {
? ? ? ? ? ? c= new ServerCookie();
? ? ? ? ? ? scookies[cookieCount]=c;
? ? ? ? }
? ? ? ? cookieCount++;
? ? ? ? return c;
? ? }
? ? /** Add all Cookie found in the headers of a request.
? ? ?*/
? ? public ?void processCookies( MimeHeaders headers ) {...
? ? /**
? ? ?* Parses a cookie header after the initial "Cookie:"
? ? ?* [WS][$]token[WS]=[WS](token|QV)[;|,]
? ? ?* RFC 2965
? ? ?* JVK
? ? ?*/
? ? public final void processCookieHeader(byte bytes[], int off, int len){...}
}
?
//為什么要多這個對象StandardSessionFacade?????
public class StandardSessionFacade implements HttpSession {
? ? private HttpSession session = null;
}
/**
?* Standard implementation of the <b>Session</b> interface. ?This object is
?* serializable, so that it can be stored in persistent storage or transferred
?* to a different JVM for distributable session support.
?* If you add fields to this class, you must
?* make sure that you carry them over in the read/writeObject methods so
?* that this class is properly serialized.
?*/
public class StandardSession implements HttpSession, Session, Serializable {
? ? /**
? ? ?* The time this session was created, in milliseconds since midnight,
? ? ?* January 1, 1970 GMT.
? ? ?*/
? ? protected long creationTime = 0L;
? ? /**
? ? ?* Return the <code>HttpSession</code> for which this object
? ? ?* is the facade.
? ? ?*/
? ? protected static HttpSessionContext sessionContext = null;?
? ? protected transient StandardSessionFacade facade = null;
? ? public HttpSession getSession() {
? ? ? ? return (facade);
? ? }
? ? /**
? ? ?* The HTTP session context associated with this session.
? ? ?*/
? ? /**
? ? ?* Inform通知 the listeners about the new session.此類中有多種多個event、listener
? ? ?*/
? ? public void tellNew() {...}
? ? /**
? ? ?* Update the accessed time information for this session. ?This method
? ? ?* should be called by the context when a request comes in for a particular
? ? ?* session, even if the application does not reference it.
? ? ?* 會被invokeHttp11NioProcessor之類的invoke(request, response)調(diào)用;
? ? ?*/
? ? public void access() {...}
} ??
?
/**
?* Standard implementation of the <b>Server</b> interface, available for use
?* (but not required) when deploying and starting Catalina.
?*
?* @author Craig R. McClanahan
?* @version $Id: StandardServer.java 1066492 2011-02-02 15:02:49Z kkolinko $
?*/
public final class StandardServer implements Lifecycle, Server, MBeanRegistration {
? ? ? ? awaitSocket = new ServerSocket(port, 1,InetAddress.getByName("localhost"));
} ??
?
好多類中都會創(chuàng)建ServerSocket比如下面這幾個: ? ? ? ? ? ? ? ?
? ? ? ? org\apache\coyote\http11\Http11Protocol.java
? ? ? ? org\apache\jk\common\ChannelNioSocket.java ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ServerSocketChannel ssc = ServerSocketChannel.open();
? ? ? ? org\apache\jk\common\ChannelSocket.java
? ? ? ? ? ? ? ? ?ServerSocket sSocket = new ServerSocket( i, backlog );
? ? ? ? org\apache\tomcat\util\net\JIoEndpoint.java
? ? ? ? ? ? ? ? ? ?serverSocket = serverSocketFactory.createSocket(port, backlog);
? ? ? ? org\apache\tomcat\util\net\NioEndpoint.java ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? serverSock = ServerSocketChannel.open();
其實創(chuàng)建一個 session 并不耗什么資源,無非就是一個空的map,就是別往里面塞太多的東西,尤其是在集群環(huán)境下,會增加同步的負擔。 ? ? ? ? ? ? ? ? ?
? 在文件《D:\study\src_zip\org\apache\catalina\core\StandardServer.java》中查找:"getInputStream"
? ? ? ? ? ? ? ? ? ? ? ? stream = socket.getInputStream(); ??
總結
以上是生活随笔為你收集整理的(精)tomcat 源码学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Web MVC是什么
- 下一篇: java类初始化顺序