微信公衆號【Java技術江湖】一位阿里 Java 工程師的技術小站。(關注公衆號後回覆”Java“即可領取 Java基礎、進階、項目和架構師等免費學習資料,更有數據庫、分佈式、微服務等熱門技術學習視頻,內容豐富,兼顧原理和實踐,另外也將贈送作者原創的Java學習指南、Java程序員面試指南等乾貨資源)
初探Tomcat的HTTP請求過程
前言:
1.作爲Java開發人員,大多都對Tomcat不陌生,由Apache基金會提供技術支持與維護,因爲其免費開源且易用,作爲Web服務器深受市場歡迎,所以有必要對其進行深入的研究,本系列皆以Tomcat 8.5爲研究課題,下載地址:https://tomcat.apache.org/download-80.cgi
2.下圖爲 apache-tomcat-8.5.23.zip 在windows解壓後的目錄。
下面是解壓後的一些關鍵目錄:
* /bin - 啓動和停止服務等批處理文件. ( *.sh) 文件 (爲Unix系統)、 (*.bat) 文件 (for Windows系統)是一個功能性的複製文件. 自從Win32 command-line 開始是一些單一的,缺乏功能的組件, 現在有一些拓展性的功能 * /conf - 配置文件和一些相關的DTD文件. 最重要的是 server.xml. 它是這個容器最主要的配置文件. * /logs - 日誌文件會打印到這裏 * /webapps - 這裏是你的應用程序部署的地方.
3.從最本質上講,tomcat爲一個servlet容器,首先研究一下Tomcat的架構,如下圖:
架構詮釋:
1.Server(服務器)是Tomcat構成的頂級構成元素,所有一切均包含在Server中,Server的實現類StandardServer可以包含一個到多個Services,Service的實現類爲StandardService調用了容器(Container)接口,其實是調用了Servlet Engine(引擎),而且StandardService類中也指明瞭該Service歸屬的Server;
2.Container: 引擎(Engine)、主機(Host)、上下文(Context)和Wraper均繼承自Container接口,所以它們都是容器。但是,它們是有父子關係的,在主機(Host)、上下文(Context)和引擎(Engine)這三類容器中,引擎是頂級容器,直接包含是主機容器,而主機容器又包含上下文容器,所以引擎、主機和上下文從大小上來說又構成父子關係,雖然它們都繼承自Container接口。
3.連接器(Connector)將Service和Container連接起來,首先它需要註冊到一個Service,它的作用就是把來自客戶端的請求轉發到Container(容器),這就是它爲什麼稱作連接器的原因。
從功能的角度將Tomcat源代碼分成5個子模塊,分別是:
Jsper模塊: 這個子模塊負責jsp頁面的解析、jsp屬性的驗證,同時也負責將jsp頁面動態轉換爲java代碼並編譯成class文件。在Tomcat源代碼中,凡是屬於org.apache.jasper包及其子包中的源代碼都屬於這個子模塊;
Servlet和Jsp模塊: 這個子模塊的源代碼屬於javax.servlet包及其子包,如我們非常熟悉的javax.servlet.Servlet接口、javax.servet.http.HttpServlet類及javax.servlet.jsp.HttpJspPage就位於這個子模塊中;
Catalina模塊: 這個子模塊包含了所有以org.apache.catalina開頭的java源代碼。該子模塊的任務是規範了Tomcat的總體架構,定義了Server、Service、Host、Connector、Context、Session及Cluster等關鍵組件及這些組件的實現,這個子模塊大量運用了Composite設計模式。同時也規範了Catalina的啓動及停止等事件的執行流程。從代碼閱讀的角度看,這個子模塊應該是我們閱讀和學習的重點。
Connector模塊: 如果說上面三個子模塊實現了Tomcat應用服務器的話,那麼這個子模塊就是Web服務器的實現。所謂連接器(Connector)就是一個連接客戶和應用服務器的橋樑,它接收用戶的請求,並把用戶請求包裝成標準的Http請求(包含協議名稱,請求頭Head,請求方法是Get還是Post等等)。同時,這個子模塊還按照標準的Http協議,負責給客戶端發送響應頁面,比如在請求頁面未發現時,connector就會給客戶端瀏覽器發送標準的Http 404錯誤響應頁面。
Resource模塊: 這個子模塊包含一些資源文件,如Server.xml及Web.xml配置文件。嚴格說來,這個子模塊不包含java源代碼,但是它還是Tomcat編譯運行所必需的。
Tomcat的組織結構
Tomcat是一個基於組件的服務器,它的構成組件都是可配置的,其中最外層的是Catalina servlet容器,其他組件按照一定的格式要求配置在這個頂層容器中。
Tomcat的各種組件都是在Tomcat安裝目錄下的/conf/server.xml文件中配置的。
由Server.xml的結構看Tomcat的體系結構
1 2 3 4 5 6 7 8 9 10 11 12 |
|
實際源碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
|
由上可得出Tomcat的體系結構:
圖一:Tomcat的體系結構
由上圖可看出Tomca的心臟是兩個組件:Connecter和Container。一個Container可以選擇多個Connecter,多個Connector和一個Container就形成了一個Service。Service可以對外提供服務,而Server服務器控制整個Tomcat的生命週期。
Tomcat Server處理一個HTTP請求的過程
圖三:Tomcat Server處理一個HTTP請求的過程
Tomcat Server處理一個HTTP請求的過程
1、用戶點擊網頁內容,請求被髮送到本機端口8080,被在那裏監聽的Coyote HTTP/1.1 Connector獲得。
2、Connector把該請求交給它所在的Service的Engine來處理,並等待Engine的迴應。
3、Engine獲得請求localhost/test/index.jsp,匹配所有的虛擬主機Host。
4、Engine匹配到名爲localhost的Host(即使匹配不到也把請求交給該Host處理,因爲該Host被定義爲該Engine的默認主機),名爲localhost的Host獲得請求/test/index.jsp,匹配它所擁有的所有的Context。Host匹配到路徑爲/test的Context(如果匹配不到就把該請求交給路徑名爲“ ”的Context去處理)。
5、path=“/test”的Context獲得請求/index.jsp,在它的mapping table中尋找出對應的Servlet。Context匹配到URL PATTERN爲*.jsp的Servlet,對應於JspServlet類。
6、構造HttpServletRequest對象和HttpServletResponse對象,作爲參數調用JspServlet的doGet()或doPost().執行業務邏輯、數據存儲等程序。
7、Context把執行完之後的HttpServletResponse對象返回給Host。
8、Host把HttpServletResponse對象返回給Engine。
9、Engine把HttpServletResponse對象返回Connector。
10、Connector把HttpServletResponse對象返回給客戶Browser。