理解思路

  • 第一:类比StandardServer, 抓住StandardService整体类依赖结构来理解

  • 第二:结合server.xml中service配置来理解

见下文具体阐述。

  • 第三:结合Service Config官方配置文档

http://tomcat.apache.org/tomcat-9.0-doc/config/service.html

Service结构设计

我们需要从高一点的维度去理解service的结构设计,而不是多少方法多少代码;这里的理解一定是要结合Server.xml中service配置部分对应理解。

server.xml

  • 首先要看下server.xml中Service的配置,这样你便知道了需要了解的4个部分

Service中的接口设计

  • 公共属性, name等

  • 父Server相关

  • Connector相关

  • Engine

  • Excutor相关

StandardService的实现

属性和父Server相关比较简单,这里主要看下其它的方法:

Engine相关

Connectors相关

Executor相关

CRUD方法,代码比较简单

Lifecycle相关模板方法

首先看 initInternal 方法

initInternal 代码很短,思路也很清晰,就是依次调用了这个成员变量的 init 方法

startInternal 方法

startInternal 跟 initInternal 方法一样,也是依次调用

补充下MapperListener

mapperListener 的作用是在 start 的时候将容器类对象注册到 Mapper 对象中。

Mapper是 Tomcat 处理 Http 请求时非常重要的组件。Tomcat 使用 Mapper 来处理一个 Request 到 Host、Context 的映射关系,从而决定使用哪个 Service 来处理请求。

MapperListener 也是继承自 LifecycleMBeanBase,不过没有重载 initInternal 方法。

  • startInternal 方法

  • findDefaultHost() 方法

首先看 findDefaultHost() 方法

findDefaultHost() 是主要是找出 defaultHost,并调用 mapper.setDefaultHostName(defaultHost); 这个 defaultHost 是 server.xml 的 <Engine> 标签的属性,一般都是 “localHost”。

从上面代码 for 代码块里可以看出,Host 是 Engine 的子 Container。for 语句就是找出一个名字跟 defaultHost 指定的名字相同的 Host 对象。

  • addListeners(engine) 方法

这个方法的作用是,将 MapperListener 这个监听器添加到 Engine 及其子容器中

  • registerHost 调用 registerHost方法来注册 Engine 的字容器 Host。

registerHost 方法先调用 mapper.addHost,然后调用 registerContext 方法注册 Host 的子容器 Context。 mapper.addHost 方法是将 Host 加入的 Mapper 类的的成员变量MappedHost[] hosts 中。

接着看 registerContext 方法

registerContext 里先获取一些对象,比如 WebResourceRoot 对象、WrapperMappingInfo 对象,然后调用 mapper.addContextVersion。

Mapper#addContextVersion 方法比较琐细,就不细讲了。

其主要逻辑是将 Context 对象,以及 Context 的子容器 Wrapper 对象,每一个都分别构建一个对应的 MappedContext 和 MappedWrapper 对象,

然后把 MappedContext 和 MappedWrapper 塞进 ContextVersion 对象中,

最后把 Context 和 ContextVersion 的对应关系放在 Mapper 对象的一个 Map 里。

这里的 MappedContext 和 MappedWrapper 在 Tomcat 处理 Http 请求的时候是比较关键的。

registerHost 最后再更新了一下可能发生改变里的的 defaultHost。