前言
終于到container容器了,上面說到connector把封裝了request對象以及response對象的socket傳遞給了container容器,那麼在contianer容器中又是怎麼樣的處理流程呢?在說container容器之前,有必要對container容器有一個簡單的了解,container容器是子容器的父接口,所有的子容器都必須實作這個接口,在tomcat中container容器的設計是典型的責任鍊設計模式,其有四個子容器:engine、host、context和wrapper。這四個容器之間是父子關系,engine容器包含host,host包含context,context包含wrapper。
我們在web項目中的一個servlet類對應一個wrapper,多個servlet就對應多個wrapper,當有多個wrapper的時候就需要一個容器來管理這些wrapper了,這就是context容器了,context容器對應一個工程,是以我們新部署一個工程到tomcat中就會新建立一個context容器。container容器的處理過程也比較複雜,下面是一個大概的流程:
上面出現了pipeline與valve,這兩個對象可以分别了解為管道與管道中閘門,當收到從connector的請求後,這個請求要通過一個個管道以及管道中一個個的閘門,隻有全部通過才能最終被具體的servlet處理。要注意的是,每一個容器都有自己的管道和閘門,這些管道與閘門都是由容器自身老控制的,是以我們可以看到注入standardenginevalve等類了。
下面就從container容器的四個子容器入手,分析每一個容器是怎麼樣處理的:
engine容器
engine容器包含host容器,根據文章第一部分的架構圖,可以知道其管理的容器是host,engine是一個接口,其标準實作類是standardengine,下面是其類結構圖:
注意其中的addchild方法,其類型是container,但是其實際管理的就是host容器。engine容器處理請求的流程可以簡化如下:
在剛開始的流程圖中調用了standardenginevalve的invoke方法,這個方法的具體實作如何呢?
代碼清單4-1:
可以看到這個方法的任務就是選擇可用的host容器處理目前的請求,選擇host容器後,就調用其invoke方法,是以具體的處理就轉移到了host容器。
host容器
host容器是engine容器的子容器,上面也說到host是受engine容器管理的,就是指一個虛拟主機,比如我們在通路具體jsp頁面url中localhost就是一個虛拟主機,其作用是運作多個應用,并對這些應用進行管理,其子容器是context,而且一個主機還儲存了主機的相關資訊。host的标準實作類是standardhost,其閘門實作是standardhostvalve,下面是standardhost與standardhostvalve的類結構圖:
host容器的處理流程可以簡化如下:
接着我們回到engine容器的invoke方法,下面是<code>host.getpipeline().getfirst().invoke(request, response)</code>的方法源碼:
代碼清單4-2:
其處理過程可以總結如下:
1. 為特定的請求url選擇一個context容器
2. 把context容器綁定到線程中
3. 判斷是否是一個異步請求
4. 讓context去處理這個請求
5. context執行invoke方法,進入管道中,由standardcontextvalve(是contextvalve的标準實作類)處理