1. 程式人生 > >Tomcat學習筆記

Tomcat學習筆記

lena gin 輸入 extc zip ket for .org 學習筆記


title: tomcat源碼學習日誌
date: 2018-07-07 23:32:43
tags:
- tomcat
- 源碼學習
categories: 技·術
---

Tomcat是什麽

Tomcat是ServletJSP、java EL表達式、WebSocket的實現。

Tomcat 7.0實現了Servlet 3.0JSP 2.2。提供了更多feature來開發和部署web應用和web服務。

官方資源匯總

  • Tomcat源碼
  • 編譯源碼步驟
  • 架構解讀
    • 核心接口描述
    • 文本描述
    • UML
    • 請求時序

編譯源碼

  • 下載Tomcat7源碼
  • 配置JDK1.6
  • 配置1.9.x版本的Ant
  • 將build.xml中的base-apache.loc.1=https://www.apache.org/dyn/closer.lua?action=download&filename=
    替換為base-apache.loc.1=https://archive.apache.org/dist
  • 在tomcat目錄下執行ant

源碼閱讀日誌

整體理解

  • 主類/主方法:org.apache.catalina.startup包下的Bootstrap類。
  • 幾個重要的目錄(或者說環境變量):
主目錄 含義
{ $CATALINA_HOME } Tomcat安裝目錄
{ $CATALINA_BASE } 每個實例分別的根目錄(可選,默認情況等同於{ $CATALINA_HOME })
CATALINA_HOME
    ├─bin       // 諸如啟動、停止等腳本。
    ├─conf      // 配置文件
    ├─logs      // 默認日誌文件路徑
    └─webapps   // web應用路徑

架構理解

名稱 意義
Server 代表整個容器。用戶基本不會變動它。提供了Server接口。
Service 作為一個生存在Server中的組件,將許多Connector與一個Engine連接,起媒介作用。
Engine 代表某個Service的請求過程。一個Service連接著多個ConntectorEngine接收這些Connector的請求,處理請求,並返回。提供了Engine接口。
Host 一個Tomcat可包含多個域名,Host則維護這些域名。t提供了Host接口和完善的實現。
Connector 用於處理與客戶端的通信。如Http Connector
Context 代表一個Web應用。一個Host包含多個Context,分別處於唯一的路徑。提供了Context和完善的實現。

按照以上概念可以繪圖:

技術分享圖片

啟動步驟

根據官方文檔,tomcat啟動序列分為兩個步驟:1)從命令行啟動 2)處理命令行參數

一、從命令行啟動

類:org.apache.catalina.startup.Bootstrap

執行內容:

  1. 安裝一系列classLoader
  2. (以反射)讀取啟動類;
  3. 完成Bootstrap.daemon.init()方法。

二、處理命令行參數(start,stop)

類:org.apache.catalina.startup.Bootstrap

執行內容(start):

  1. Catalina.setAwait(true)
  2. Catalina.load():
    1. 初始化基本文件夾:initDirs() -> 設置諸如catalina.home/case等屬性;
    2. 初始化命名服務:setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,org.apache.naming.java.javaURLContextFactory ->default)
    3. 創建xml文件轉化器:createStartDigester()
    4. 讀取server.xml並用轉化器(digester)將其解析。digester是一個“XML-對象”映射器,將根據server.xml定義的內容創建對象。到目前為止,容器其實還沒有開始初始化。
    5. System.outSystem.err分配給SystemLogHandler類。
    6. 調用所有組件的初始化方法。此步驟將令每個對象通過JMX代理註冊其本身。在此步驟中,Connector也將初始化適配器。適配器也是一種組件,用來執行請求預處理。例如HTTP1.1適配器:org.apache.coyote.http11.Http11Protocol
  3. Catalina.start():
    1. 啟動NamingContext,將所有JNDI引用綁定其中。
    2. 啟動Server下的所有service。此步驟啟動引擎(Engine)。
    3. 啟動主機:StandardHost
      1. 配置一個錯誤閥門,用於將不同的HTTP錯誤碼為HTML。
      2. 設置標準主機閥門,將web應用的類加載器與線程上下文綁定,它也用來為請求找到相應的session
      3. 啟動HostConfig組件。此組件部署所有web應用,即webappconf/Catalina/localhost/*.xml
      4. HostConfig將為上下文創建一個Digester,它將調用ContextConfig.start()。這個方法將處理默認的web.xmlconf/web.xml,然後處理所有的應用web.xmlWEB-INF/web.xml
    4. 在容器的生命周期中,存在一個後臺線程,用來不斷檢查上下文(context)是否改變,即war文件、context文件、web.xml文件等的改變。如果改變,則重新加載。(stop/remove/deploy/start
  4. 當Tomcat(在HTTP端口)接收到一個請求時:
    1. 該請求將被一個獨立的線程接收。此線程在ThreadPoolExecutor類中。它在一個ServerSocket.accpet()方法中等待請求。
    2. ThreadPoolExecutor分配一個TaskThread來處理此請求。
    3. 處理器(processor)處理該請求。如果是HTTP請求,則是Coyote Http11Processor來處理。調用了process方法。此處理器將繼續檢查socket的輸入流,直到連接斷開,或者達到keep alive point
    4. 此HTTP請求將被內部的緩沖類(Http11InputBuffer)解析。此解析類將解析出請求行、請求頭等等,將結果存儲在一個Coyote請求中。此request包含所有的HTTP信息,如servernameportscheme等。
    5. 處理器維護著一個Adapter(引用),在本例中是CoyoteAdapter。一旦請求已經被解析,那麽Http11Processor調用該adapterservice()方法。在此service方法中,Request包含一個CoyoteRequest和一個CoyoteResponse(第一次則為null)。CoyoteRequest(Response)實現了HttpRequest(Response)HttpServletRequest(Response)。適配器通過Mapper來處理requestcontext等。
    6. 當解析完成之後,CoyoteAdapter調用它的容器(StandardEngine),調用所有的invoke()方法。
    7. StandardEngine.invoke()方法調用容器的pipeline.invoke()方法。
    8. StandardHostValve調用與request相關的context上的pipeline
    9. Context pipeline調用的第一個閥門是FormAuthenticator閥門。接下來是StandardContextValveStandardContextValve調用與context相關的所有上下文監聽器。然後調用Wrapper組件的所有pipeline
    10. 編譯JSP,調用實際的servlet
  5. servlet類的調用

優美代碼

觀察到,一個典型的類中,可以被分成:

    // ------------------------------------------------------- Static Variables
    // -------------------------------------------------------------- Variables
    // -------------------------------------------------------- Private Methods
    // ----------------------------------------------------------- Main Program

典型的生命周期方法有:

    public void init()
    public void init(String[] arguments)
    public void start()
    public void stop()
    public void stopServer()
    public void stopServer(String[] arguments)
    public void destroy()

Tomcat學習筆記