整體架構(gòu)圖

Connector(連接器)
功能需求:
- 監(jiān)聽網(wǎng)絡(luò)端口
- 接受網(wǎng)絡(luò)連接請求
- 讀取請求網(wǎng)絡(luò)字節(jié)流
- 根據(jù)具體應(yīng)用層協(xié)議(HTTP/AJP)解析字節(jié)流,生成統(tǒng)一的Tomcat Request對象
- 將Tomcat Request對象轉(zhuǎn)成標(biāo)準(zhǔn)的ServletRequest
- 調(diào)用Servlet容器,得到ServletResponse
- 將ServletResponse轉(zhuǎn)成 Tomcat Response對象
- 將Tomcat Response對象轉(zhuǎn)成網(wǎng)絡(luò)字節(jié)流
- 將響應(yīng)字節(jié)流寫會服務(wù)器
分析
連接器需要完成三個高內(nèi)聚的工作
- 網(wǎng)絡(luò)通信--Endpoint
- 應(yīng)用層協(xié)議解析--Processor
- Tomcat Request/Response 與 Servlet Request/Response 的轉(zhuǎn)化--Adapter
處理邏輯
Endpoint負(fù)責(zé)提供字節(jié)流給Processor,Processor負(fù)責(zé)提供Tomcat Request 對象給Adapter,Adapter 負(fù)責(zé)提供ServletResponse對象給容器
由于I/O模型和應(yīng)用層協(xié)議可以自由組合,所以設(shè)計了一個ProtocolHandler的接口來封裝這兩種變化點(diǎn),
由于還存在一些穩(wěn)定的部分,Tomcat設(shè)計了一系列抽象類來封裝。它們的繼承關(guān)系如下圖所示:

ProtocolHandler組件
連接器用ProtocolHandler來處理網(wǎng)絡(luò)連接和應(yīng)用層協(xié)議,包含兩個重要組件:Endpoint 和 Processor。
Endpoint
Endpoint是通信端點(diǎn),即通信監(jiān)聽的接口,是具體的Socket接受和發(fā)送處理器,是對傳輸層的抽象,因此endpoint是用來實(shí)現(xiàn)TCP/IP協(xié)議的。
Endpoint是一個接口,對應(yīng)的抽象實(shí)現(xiàn)類是AbstractEndpoint(org.apache.tomcat.util.net.AbstractEndpoint),而AbstractEndpoint的具體子類,比如在NioEndpoint和Nio2Endpoint中,有兩個重要的子組件:Acceptor(一個實(shí)現(xiàn)了Runable接口的抽象類,在NioEndpoint等類中有具體實(shí)現(xiàn)) 和 SocketProcessor。
其中Acceptor用于監(jiān)聽Socket連接請求。SocketProcessor用于處理接收到的Socket請求,他事先Runnable接口,在Run方法里調(diào)用協(xié)議處理組件Processor進(jìn)行處理。為了提高處理能力,SocketProcessor 被提交到線程池來執(zhí)行。這個線程池叫執(zhí)行器(Executor),擴(kuò)展了原生的Java線程池。
Processor
如果說 Endpoint 是用來實(shí)現(xiàn) TCP/IP 協(xié)議的,那么 Processor 就是用來實(shí)現(xiàn)HTTP協(xié)議,Processor 接受來自Endpoint的Socket,讀取字節(jié)流解析成 Tomcat Request 和 Response 對象,并通過 Adapter 將其提交到容器處理,Processor 是對應(yīng)用層協(xié)議的抽象。
Processor 是一個接口,定義了請求的處理等方法。它的抽象實(shí)現(xiàn)類 org.apache.coyote.AbstractProcessor 對一些協(xié)議共有的屬性進(jìn)行封裝,沒有對方法進(jìn)行實(shí)現(xiàn)。具體的實(shí)現(xiàn)協(xié)議有 AJPProcessor 、HTTP!!Processor 等,這些具體實(shí)現(xiàn)類實(shí)現(xiàn)了特定協(xié)議的解析方法和請求處理方式。

從圖中我們看到,Endpoint 接收到 Socket 連接后,生成一個SocketProcessor 任務(wù)提交到線程池去處理,SocketProcessor 的 Run 方法會調(diào)用 Processor 組件去解析應(yīng)用層協(xié)議,Processor 通過解析生成 Request 對象后,會調(diào)用 Adapter 的 Service 方法。
Adapter組件
由于協(xié)議不同,客戶端發(fā)過來的請求信息也不盡相同,Tomcat定義了自己的Request(org.apache.coyote.Request)類來“存放”這些請求信息。ProtocolHandler 接口負(fù)責(zé)解析請求并生成 Tomcat Request 類。但是這個Request對象并不是標(biāo)準(zhǔn)的ServletRequest,也就意味著,不能用 Tomcat Request 作為參數(shù)來調(diào)用容器。 Tomcat設(shè)計者的解決方案是引入 CoyoteAdapter(org.apache.catalina.connector.CoyoteAdapter),這是適配器模式的經(jīng)典運(yùn)用,連接器調(diào)用CoyoteAdapter的Service方法,傳入的是 Tomcat Request 對象,CoyoteAdapter 負(fù)責(zé)將 Tomcat Request 對象轉(zhuǎn)成 ServletRequest,再調(diào)用容器的 Service 方法。