你確定你瞭解Tomcat嗎(一)?

各位看官老爺大家好,我又寫完了一篇枯燥且無味的博客,火速前來發布

Tomcat

身爲一個整天和web打交道java碼農,Tomcat是我們整天擡頭不見低頭見的好朋友,好工具, 但是好朋友要做到互相瞭解,所以,這篇文章幫你瞭解Tomcat,做他的好朋友,這樣,下次它不高興報錯的時候我們也可以對症下藥…
我們平時用框架開發出的java後端程序,部署到Tomcat中才可以發揮它的作用,所以,Tomcat其實是一個本地服務,我們將我們的java程序放入其中,然後啓動Tomcat服務,其他電腦就可以通過網絡訪問我們的tomcat,來訪問我們的程序。

接下來請大家坐穩扶好,前往tomcat底層架構的列車即將啓動......

在我們學習tomcat的時候,可能最常聽到的就是tomcat是一個servlet容器, 如果要我們用代碼寫的話,可能就是這個樣子的

class Tomcat{
	List<Servlet> servlets;
}


如圖所示(如果看不懂這個的客官老爺出門左轉不送),這是一個簡單的servlet,我們都知道,servlet是tomcat用來處理我們的請求的,那麼它是如何處理我們的請求的呢?肯定有看官老爺就要說了,調用doGet方法呀!
對,確實是這樣,但是我們在調用方法時,一般是這樣的

IServlet servlet = new IServlet();
servlet.doGet(request, response);

於是,我們會有這樣一個疑問,在tomcat中,這個doGet方法的調用是不是形如這個樣子呢?還有,當我們ctrl + 左鍵點入HttpServletRequest的源碼的時候,我們會發現它是一個接口,同樣,HttpServletResponse也是一個接口,那麼,我們就又有一個疑問了,當我們調用doGet方法的時候,傳入的HttpServletRequest或者是HttpServletResponse類型的實際對象是什麼呢?

這時,有觀衆老爺就要說了,媽的,少給老子賣關子,小心改日登門拜訪

別激動,別激動…其實我們的這兩個接口的實現類是由其對應的容器進行實現的,就是說,如果你將應用程序部署到tomcat,就是tomcat給我們進行實現,如果部署到jetty的話,就是jetty給我們進行實現的。可以這麼理解,我們的這兩個接口其實是HttpServlet的規範,我們的容器對這個接口的實現類,就相當於是對這個規範的實現。
那麼,這兩個接口在tomcat中的實現類是什麼呢?

RequestFacade req = (RequestFacade) request;

如果大家在上面那張圖的基礎上,將這句代碼加到打印輸出的上面,會發現程序運行後,是可以正常打印出結果的,看到這裏,各位看官老爺是不是明白了什麼羞羞的東西呢?

tomcat在實現RequestFacade的時候,其實並不是將HttpServletRequest中的方法在這個類中都進行了實現,它是調用了它內部的一個叫做Request request的一個屬性,所有具體的實現在這個Request類中,而RequestFacade這個類就像它的名字一樣,是tomcat用來暴露給外面的人使用的,所以說,當tomcat處理完請求的時候,生成的是一個Request類。
所以說Request是一個核心類,而RequestFacade是Tomcat的一個用於實現HttpServlet約束的一個門面類。

Tomcat中的容器類

在tomcat中有四個類繼承了Container容器類, 分別是Context, Wrapper, Host, Engine, 它們分別是做什麼的呢?
Context就像上邊說的,他代表的是我們的應用程序,我們的每一個應用程序都是一個Context.
Host代表了我們的虛擬主機, 它包括了Context,我們通常在url中寫的localhost就是一個默認的虛擬主機,我們還可以自定義配置其他的虛擬主機,在server.xml文件中進行配置即可
Engine就好像是一個集羣,它包括的很多虛擬主機
Wrapper: 當我們的servlet不是單例模式的時候,wrapper就是管理同一個servlet類型的不同實例, 假如說我有一個servlet類叫做MyServlet,我這個類對應的有很多實例,wrapper就是用來管理這些實例的。
像這樣,我們將我們上面第一段代碼進行修改, 真實的場景應該是這樣的

Class Context{
	List<Wrapper> wrappers;
}
Class Wrapper{
	List<Servlet> servlets;
}
各位觀衆老爺是不是明白了點什麼?

tomcat之所以被稱爲servlet容器,可就是靠的這些容器類!!
所以各個容器的大小應該是
Engine > Host > Context > Wrapper > Servlet
每一個容器下面其實並非只有下一層容器的一個集合,其實還有一個組件,叫做pipline,會對我們的請求進行過濾,每一個pipline的最後一個過濾器都是tomcat自己內置的,用來向下一層的容器進行傳遞。

ps:其實tomcat在最後使用servlet實例調用我們的doGet方法的時候,其實並不是直接調用doGet方法,而是調用的service方法。
這時一些看官老爺就要問了,我的servlet沒有service方法啊,確實,你是沒有寫,但是你繼承的HttpServlet寫了啊

war包和jar包的區別是什麼呢?

當我們沒有靜態資源的時候,同時,將servlet的註冊換成註解的形式(也就是web.xml文件也沒有的時候), 從外表上來看,war包的內容和jar包是一樣的,那麼它們到底有什麼區別呢?
其實,如果沒有war包的話,tomcat是沒有辦法在webapps目錄下判斷你放的jar包究竟是你的應用程序還是你程序中引入的其他的jar包的,所以,就出現了war包。

在這裏插入圖片描述
大家可以看到,在以war包進行部署的時候,tomcat中源碼是寫死的,會根據.war進行尋找,所以這就是爲什麼需要war包

Tomcat進行部署項目的幾種方式

在這裏插入圖片描述
大家請看上圖,在tomcat中的源碼已經寫的很明確了,三種,以文件夾和war包的部署方式我們都清楚,那什麼是以xml文件的部署形式呢?
其實哈,這裏的xml文件指的就是我們tomcat中的server.xml(config文件夾下)文件
在這裏插入圖片描述
大家請看這個圖片,其實,我們將文件夾和war包放入webapps的目錄下時,其實是手動的將其可以被tomcat找到,我們也可以不將我們的文件夾和war文件放入webapps目錄下,通過在server.xml中配置context這個節點, 通過配置docbase這個屬性來使tomcat可以找到你的放在別處的工程, 這就是xml的方式。
這裏有一個優先級的順序,xml > war文件 > 文件夾的形式

最後,又到了說再見的時候了。
但是我們的旅途還沒有結束,tomcat還有很多的知識等待我們去探索
如果本文有什麼不妥的地方,歡迎留言指出,我們共同進步
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章