Tomcat學習筆記
阿新 • • 發佈:2018-07-20
lena gin 輸入 extc zip ket for .org 學習筆記
title: tomcat源碼學習日誌
date: 2018-07-07 23:32:43
tags:
- tomcat
- 源碼學習
categories: 技·術
---
Tomcat是什麽
Tomcat是Servlet
、JSP
、java EL表達式、WebSocket
的實現。
Tomcat 7.0實現了Servlet 3.0
和JSP 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 連接著多個Conntector ,Engine 接收這些Connector 的請求,處理請求,並返回。提供了Engine 接口。 |
Host | 一個Tomcat可包含多個域名,Host則維護這些域名。t提供了Host 接口和完善的實現。 |
Connector | 用於處理與客戶端的通信。如Http Connector |
Context | 代表一個Web應用。一個Host 包含多個Context ,分別處於唯一的路徑。提供了Context 和完善的實現。 |
按照以上概念可以繪圖:
啟動步驟
根據官方文檔,tomcat啟動序列分為兩個步驟:1)從命令行啟動 2)處理命令行參數
一、從命令行啟動
類:org.apache.catalina.startup.Bootstrap
執行內容:
- 安裝一系列
classLoader
; - (以反射)讀取啟動類;
- 完成
Bootstrap.daemon.init()
方法。
二、處理命令行參數(start,stop)
類:org.apache.catalina.startup.Bootstrap
執行內容(start):
Catalina.setAwait(true)
;Catalina.load()
:- 初始化基本文件夾:
initDirs()
-> 設置諸如catalina.home/case
等屬性; - 初始化命名服務:
setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,org.apache.naming.java.javaURLContextFactory ->default)
- 創建xml文件轉化器:
createStartDigester()
- 讀取
server.xml
並用轉化器(digester)將其解析。digester是一個“XML-對象”映射器,將根據server.xml
定義的內容創建對象。到目前為止,容器其實還沒有開始初始化。 - 把
System.out
和System.err
分配給SystemLogHandler
類。 - 調用所有組件的初始化方法。此步驟將令每個對象通過
JMX
代理註冊其本身。在此步驟中,Connector
也將初始化適配器。適配器也是一種組件,用來執行請求預處理。例如HTTP1.1適配器:org.apache.coyote.http11.Http11Protocol
- 初始化基本文件夾:
Catalina.start()
:- 啟動
NamingContext
,將所有JNDI
引用綁定其中。 - 啟動
Server
下的所有service
。此步驟啟動引擎(Engine)。 - 啟動主機:
StandardHost
。- 配置一個錯誤閥門,用於將不同的HTTP錯誤碼為HTML。
- 設置標準主機閥門,將web應用的類加載器與線程上下文綁定,它也用來為請求找到相應的
session
。 - 啟動
HostConfig
組件。此組件部署所有web應用,即webapp
和conf/Catalina/localhost/*.xml
HostConfig
將為上下文創建一個Digester
,它將調用ContextConfig.start()
。這個方法將處理默認的web.xml
即conf/web.xml
,然後處理所有的應用web.xml
即WEB-INF/web.xml
。
- 在容器的生命周期中,存在一個後臺線程,用來不斷檢查上下文(context)是否改變,即
war
文件、context
文件、web.xml
文件等的改變。如果改變,則重新加載。(stop/remove/deploy/start
)
- 啟動
- 當Tomcat(在HTTP端口)接收到一個請求時:
- 該請求將被一個獨立的線程接收。此線程在
ThreadPoolExecutor
類中。它在一個ServerSocket.accpet()
方法中等待請求。 ThreadPoolExecutor
分配一個TaskThread
來處理此請求。- 處理器(
processor
)處理該請求。如果是HTTP請求,則是Coyote Http11Processor
來處理。調用了process
方法。此處理器將繼續檢查socket
的輸入流,直到連接斷開,或者達到keep alive point
。 - 此HTTP請求將被內部的緩沖類(
Http11InputBuffer
)解析。此解析類將解析出請求行、請求頭等等,將結果存儲在一個Coyote
請求中。此request
包含所有的HTTP信息,如servername
,port
,scheme
等。 - 處理器維護著一個
Adapter
(引用),在本例中是CoyoteAdapter
。一旦請求已經被解析,那麽Http11Processor
調用該adapter
的service()
方法。在此service
方法中,Request
包含一個CoyoteRequest
和一個CoyoteResponse
(第一次則為null)。CoyoteRequest(Response)
實現了HttpRequest(Response)
和HttpServletRequest(Response)
。適配器通過Mapper
來處理request
和context
等。 - 當解析完成之後,
CoyoteAdapter
調用它的容器(StandardEngine
),調用所有的invoke()
方法。 StandardEngine.invoke()
方法調用容器的pipeline.invoke()
方法。StandardHostValve
調用與request
相關的context
上的pipeline
。- 被
Context pipeline
調用的第一個閥門是FormAuthenticator
閥門。接下來是StandardContextValve
。StandardContextValve
調用與context
相關的所有上下文監聽器。然後調用Wrapper
組件的所有pipeline
。 - 編譯JSP,調用實際的
servlet
。
- 該請求將被一個獨立的線程接收。此線程在
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學習筆記