沒有人永遠年輕,但永遠有人年輕
之前手寫了一個能解析Servlet的簡單的Servlet容器,但是我們的目標可不能止於這些,把Tomcat寫出來纔是我們最終的目標~
- 相關代碼已同步Github
概述
我們知道Catalina
中有兩個主要的板塊,一個是connector
,另外一個是container
。
- 連接器負責將請求和容器關聯,它爲每一個Http請求創建一個request和response對象。然後把這兩個對象交給容器
- 容器接收到對象之後,調用request請求的servlet的service方法。之後,把處理的結果以response返回回去
連接器主要類
相對於上一篇博客的服務器,我們把要寫的類分爲以下幾個類型:
- 啓動類:
Bootstrap
- 連接器類
HttpConnector
和HttpProcessor
上一章是HttpServerHttpConnector
等待Http請求HttpProcessor
創建HttpRequest
和HttpResponse
實例
HttpRequest
和其支持類 上一章是RequestHttpResponse
和其支持類 上一章是Response- Http的外觀類(之前已經實現過)
- 常量類
HttpHeader
主要用於解析請求頭HttpRequestLine
主要用於解析請求行Constants
主要是路徑
- 核心模塊
ServletProcessor
StaticResourceProcessor
處理流程
本程序的服務器流程是:
- 先是
Boostrap
啓動服務器,然後HttpConnect
等待客戶端的請求。 - 當請求到達時,服務器會新開一個線程接收該請求,拿到
socket
後,把socket
傳給HttpProcessor
,同時HttpProcessor
處理該socket。 HttpProcessor
會執行四個操作,創建HttpRequest
對象和HttpResponse
對象,解析Http請求的請求行和請求頭信息,填充HttpRequest
對象。HttpRequest
會去獲得參數,而不是通過HttpProcessor
來獲取,因爲我們不知道servlet是否需要這些參數,這樣可以減少資源消耗- 之後,將
HttpRequest
對象和HttpResponse
對象傳遞給ServletProcessor
或者StaticResourceProcessor
的process()
方法。對於前者來說,其process方法會先找到自定義的Servlet類,然後調用其service方法;對於後者說,其process方法會直接讀取靜態文件。 - 之後,把內容填充到
HttpResponse
中,返回給客戶端
UML類圖
其中,
org.apache.catelina.util.StringManager
類用於處理不同模塊的錯誤消息和國際化操作
- 同一個包下的類共用一個StringManager實例 通過單例模式實現
- 每個包使用一個
properties
來說明該包中任何類可能出現的異常信息,每個異常信息都是kv的形式