7.3.1 ContainerBase的结构
Container 是 Tomcat 中容器的接口,其一共有四个子接口 Engine、Host、Context、Wrapper 一个默认实现类 ContainerBase,每个子接口都是一个容器,每个接口都有一个对应的 StandardXXX 实现类,并且都继承自 ContainerBase。同时 Container 还继承了 Lifecycle 借口,其和其子类都符合之前的生命周期管理模式。
Container 结构图7.3.2 Container 的4个子容器
Container 的子容器是逐级包含的关系:
- Engine:引擎,用于管理多个站点,一个Service 只能有一个 Engine。
- Host:代表一个站点,也可以叫虚拟主机,通过配置 Host 就可以添加站点。
- Context:代表一个应用程序,对应平时开发的一套程序,或者一个 WEB-INF 目录以及下面的 web.xml 文件。
-
Wrapper: 每个 Wrapper 封装一个 Servlet。
Container 容器装配结构图
7.3.3 4种容器的配置方式‘
略
7.3.4 Container 的启动
Container 的启动通过 init 和 start 方法来完成,这两个方法会在 Tomcat 启动时被 Service 调用。Container 继承 Lifecycle 所以也是按照 Tomcat 的生命周期来管理,通过 init 和 start 进行初始化并调用子类的 initInternal 和 startInternal 方法进行具体处理,但是之前 Tomcat 整体结构的启动过程有所不同:
- Container 的4个子容器有一个共同的父类 ContainerBase,这里定义了 Container 容器的 initInternal 和 startInternal 方法通用处理内容。
- 除了最顶层容器的 init 是被 Service 调用的,子容器的 init 方法并不是在容器中逐层循环调用的,而是在执行 start 方法是时候通过状态判断还没有初始化才调用的(这是相对生命周期方法而言)。
- start 方法除了在父容器的 startInternal 方法中调用,还会在父容器的添加子类的 addChild 方法中调用,这主要是因为 Context 和 Wrapper 是动态添加的,我们在站点目录下放一个应用的文件夹或者 war 包就可以添加一个 Context,在 web.xml 中配置一个 Servlet 就可以添加一个 Wrapper,所以 Context 和 Wrapper 都是在容器启动过程中才动态查找出来添加到相应的父容器中的。
ContainerBase
containerBase 的** initInternal **方法主要是初始化 ThreadPollExecutor 类型的 startStopExecutor 属性,用于管理启动关闭的线程
initInternal 方法containerBase 的 startInternal 方法主要做了5件事:
- 如果有 Cluster 和 Realm 则调用其 start 方法;
- 调用所有子容器的 start 方法启动子容器;
- 调用管道的中 Valve 的 start 方法来启动管道;
- 启动完成后将生命周期状态设置为 LifecycleState.STRATING 状态;
- 启动后台线程定时处理一些事情。
- Cluster 用于配置集群,作用是同步session。
- Realm 是 Tomcat 的安全域,可以用来管理资源的访问权限。
- 子容器使用 startStopExecutor 调用新线程来启动,可以提高效率。遍历future有两个作用:
- 其get方法是阻塞的,保证管道Pipeline 启动前容器就已经启动完成。
- 可以处理启动过程中遇到的异常。
- 启动子容器的线程类型是 StartChild 是一个实现了Callable 的的内部类在 call 方法中调用注入子类的 start 方法。
- 因为这里的 startInternal 是 ContainerBase 的方法,而所有的容器类都继承了 ContainerBase ,所以所有容器都会在启动过程中调用子类的 start 方法启动子容器。
Engine
Service 会调用最顶层容器的 init 和 start 方法,如果使用了 Engine 就会调用 Engine 的生命周期方法
Engine 对应方法Host
Host 的默认实现类 StandardHost 没有重写 initInternal 方法,所以会调用ContainerBase 的 initInternal 方法。重写了 startInternal 方法: startInternal 方法主要检查 Host 管道中是否有指定的 Valve(阀) ,如果没有则添加。
StandardHost startInternal 方法Context
Context 的默认实现类 StandardContext 的 startInternal 方法会调用 web.xml 中定义的 Listener,另外还初始化了其中的 Filter 和 load-on-startup 的Servlet。
Standard Context startInternal 方法Wrapper
StandardWrapper没有重写 initInternal 方法,重写了 startInternal 方法
- 用 broadcaster 发送通知,主要用于 JMX;
- 调用了父类 ContainerBase 的initInternal 方法;
- 调用 setAvailable 方法让 Servlet 有效
网友评论