原文出处:
Rainstorm
这个题目命的其实是很大的,写的时候还是很忐忑的,但我尽可能把这个过程描述清楚。因为这是读过源码以后写的总结,在写的过程中可能会忽略一些前提条件,如果有哪些比较突兀就出现,或不好理解的地方可以给我提 Issue,我会尽快补充修订相关内容。
很多东西在时序图中体现的已经非常清楚了,没有必要再一步一步的作介绍,所以本文以图为主,然后对部分内容加以简单解释。
- 绘制图形使用的工具是 PlantUML + Visual Studio Code + PlantUML Extension
- 图形
PlantUML
源文件:
本文对 Tomcat 的介绍以 Tomcat-9.0.0.M22
为标准。
Tomcat-9.0.0.M22
是 Tomcat 目前最新的版本,但尚未发布,它实现了 Servlet4.0
及 JSP2.3
并提供了很多新特性,需要 1.8 及以上的 JDK 支持等等,详情请查阅 Tomcat-9.0-doc
- Overview
- Tomcat init
- Tomcat Start[Deployment]
- Background process
- How to read excellent open source projects
- At last
- Reference
Overview
Bootstrap
作为 Tomcat 对外界的启动类,在$CATALINA_BASE/bin
目录下,它通过反射创建Catalina
的实例并对其进行初始化及启动。Catalina
解析$CATALINA_BASE/conf/server.xml
文件并创建StandardServer
、StandardService
、StandardEngine
、StandardHost
等StandardServer
代表的是整个 Servlet 容器,他包含一个或多个StandardService
StandardService
包含一个或多个Connector
,和一个Engine
,Connector
和Engine
都是在解析conf/server.xml
文件时创建的,Engine
在 Tomcat 的标准实现是StandardEngine
MapperListener
实现了LifecycleListener
和ContainerListener
接口用于监听容器事件和生命周期事件。该监听器实例监听所有的容器,包括StandardEngine
、StandardHost
、StandardContext
、StandardWrapper
,当容器有变动时,注册容器到Mapper
。Mapper
维护了 URL 到容器的映射关系。当请求到来时会根据Mapper
中的映射信息决定将请求映射到哪一个Host
、Context
、Wrapper
。Http11NioProtocol
用于处理 HTTP/1.1 的请求NioEndpoint
是连接的端点,在请求处理流程中该类是核心类,会重点介绍。CoyoteAdapter
用于将请求从 Connctor 交给 Container 处理。使 Connctor 和 Container 解耦。StandardEngine
代表的是 Servlet 引擎,用于处理Connector
接受的 Request。包含一个或多个Host
(虚拟主机),Host
的标准实现是StandardHost
。StandardHost
代表的是虚拟主机,用于部署该虚拟主机上的应用程序。通常包含多个Context
(Context 在 Tomcat 中代表应用程序)。Context
在 Tomcat 中的标准实现是StandardContext
。StandardContext
代表一个独立的应用程序,通常包含多个Wrapper
,一个Wrapper
容器封装了一个 Servlet,Wrapper
的标准实现是StandardWrapper
。StandardPipeline
组件代表一个流水线,与Valve
(阀)结合,用于处理请求。StandardPipeline
中含有多个Valve
, 当需要处理请求时,会逐一调用Valve
的invoke
方法对 Request 和 Response 进行处理。特别的,其中有一个特殊的Valve
叫basicValve
,每一个标准容器都有一个指定的BasicValve
,他们做的是最核心的工作。StandardEngine
的是StandardEngineva lve
,他用来将 Request 映射到指定的Host
;StandardHost
的是StandardHostValve
, 他用来将 Request 映射到指定的Context
;StandardContext
的是StandardContextValve
,它用来将 Request 映射到指定的Wrapper
;StandardWrapper
的是StandardWrapperValve
,他用来加载 Rquest 所指定的 Servlet,并调用 Servlet 的Service
方法。
Tomcat init
- 当通过
./startup.sh
脚本或直接通过java
命令来启动Bootstrap
时,Tomcat 的启动过程就正式开始了,启动的入口点就是Bootstrap
类的main
方法。 - 启动的过程分为两步,分别是
init
和start
,本节主要介绍init
;
- 初始化类加载器。[关于 Tomcat 类加载机制,可以参考我之前写的一片文章:谈谈Java类加载机制]
- 通过从
Ca