Tomcat源碼學習探索筆記

如今tomcat源碼量很是大,想讀懂那麼多人寫的代碼很耗時間,這裏記下我學習tomcat的一點筆記java

TomcatWeb服務器git

幾個月前我本科沒畢業的時候,還不知道web服務器和應用服務器的區別github

用我本身的話描述,本身的程序裏帶jar文件來支持JavaEE組件的是web服務器web

socket開始bootstrap

我以爲不少中間件源碼讀起來很困難,由於咱們只看到了最終的產品,中間發展的過程以及增長的功能咱們並不清楚.瀏覽器

Tomcat如今的源碼量至關的大,即便讀一些解讀的文章再調試也不容易理解透徹,並且在業務團隊裏也不必死摳每一個技術細節,因此我以爲應該按部就班tomcat

我先寫一個最簡單的Socket,啓動時只要用瀏覽器訪問 localhost:8080 就能夠看到socket 傳來的信息,並能看返回當前系統時間
收到的消息
 
服務器

返回的結果

多線程

Socket改進app

一個socket雖然很簡單,但咱們能夠明白HTTP協議的原理

若是咱們把它改進一下,input封裝到Request,output封裝到response,就好理解多了

我在github上找到一個挺有意思的東東

https://github.com/dasanjos/java-WebServer

我稍微改動了一下這個代碼,讓它變得更直觀些

它就是把我上面寫的代碼改爲線程池管理,並把socket經過handler傳給線程,分爲RequestResponse,支持了本地文件的讀寫
 

RequestHandler處理過程
 

執行效果

雖然和上面的代碼相比不過就是封裝了一下罷了

但線程池把socket監聽請求以及io流的處理給分開了,其實這個過程就是tomcatconnectorcontainer經過HttpProcessor傳遞socket的過程的簡化,Main裏管線程池的代碼咱們能夠封裝到一個叫Connector裏面,有請求就從池子裏取個線程,讓它合成RequestResponse,把它上交給.....容器

Classloader原理

其實作到上一步,基本能夠把這坨代碼當webServer跑了,但它不支持servlet,也沒有webapps目錄和Context,並且咱們都是打war包的,war包裏的那些類tomcat是怎麼調用的?

由於tomcatclassloader是封裝到Context裏面的,這個加載過程很差解釋,我就寫一個簡單的例子說明一下:

這個目錄結構至關簡單,folder下有個編譯好的B,咱們啓動tomcat而後啓動服務的過程能夠視爲Main類跑時把B類也加載進去


爲了更有說服力,咱們能夠先ps -ef|grep java 肯定 folder不在咱們的classpath裏面

而後VM參數加上-verbose:class 親眼看看B這個class文件是怎麼被加載進去的


在學校的時候配java環境變量,老是要把rt.jar 這堆玩意加到classpath,時間久了基本背下來要加哪些包了

Javaclassloader分爲 bootstrap classloader,extension classloadersystem classloader,其實rt.jar裏的那些java核心類就是bootstrap classloader給加進去的,咱們能夠執行如下這個代碼看看bootstrap classloader都加載了什麼


Tomcat結構

寫了這麼多卻一直沒提tomcat有些三紙無驢的感受,但其實寫到這裏,咱們本身就能寫個很是粗陋的支持servletwebServer相似物了

我學習tomcat源碼不只是由於好奇,爲了方便定位問題,也是爲了瞭解一點它的設計思想

我畫了個草圖,並按本身當即標註了一下這些組件是幹啥的,大體說明一下tomcat的結構


固然,這裏面還有一些Loader, Pipeline ,Valve ,Repository 這類的小東西我沒標,否則圖就太亂了

由一個Socket忽然變得這麼複雜稍微有點過分不天然,也不要緊,我在萬能的github上又找到一個過分天然的項目

https://github.com/luminocean/Tommycat

這個項目麻雀雖小五臟俱全,雖然沒Server.xml配置文件,tomcat該有的它基本都有,只是容器只有ContextWrapper,但看懂這個基本就明白tomcat的設計思想了

這個項目下面有個Mushroom的項目,主項目跑起來,會把Mushroom放到Context容器裏,並經過Loader加載裏面編譯好的class

這裏沒有filter,因此若是訪問的uri直接能找到文件就直接返回文件內容,找不到就會從ContextValvemap裏找加載好的Servlet而後invoke調用

這裏面還有個LifeCycle接口,就是我們常說的生命週期,每一個容器都實現了這個接口裏的方法

我讀源碼的辦法

我是先debug,debug邊看涉及到的類結構,由於這是多線程的,單純debug不是很好理解

我把主要的類摳出來,只保留類裏重要的域,debug一遍就能明白類之間的調用關係

相關文章
相關標籤/搜索