天天看点

深入理解Tomcat系列之四:Engine和Host容器

前言

终于到container容器了,上面说到connector把封装了request对象以及response对象的socket传递给了container容器,那么在contianer容器中又是怎么样的处理流程呢?在说container容器之前,有必要对container容器有一个简单的了解,container容器是子容器的父接口,所有的子容器都必须实现这个接口,在tomcat中container容器的设计是典型的责任链设计模式,其有四个子容器:engine、host、context和wrapper。这四个容器之间是父子关系,engine容器包含host,host包含context,context包含wrapper。

我们在web项目中的一个servlet类对应一个wrapper,多个servlet就对应多个wrapper,当有多个wrapper的时候就需要一个容器来管理这些wrapper了,这就是context容器了,context容器对应一个工程,所以我们新部署一个工程到tomcat中就会新创建一个context容器。container容器的处理过程也比较复杂,下面是一个大概的流程:

深入理解Tomcat系列之四:Engine和Host容器

上面出现了pipeline与valve,这两个对象可以分别理解为管道与管道中闸门,当收到从connector的请求后,这个请求要通过一个个管道以及管道中一个个的闸门,只有全部通过才能最终被具体的servlet处理。要注意的是,每一个容器都有自己的管道和闸门,这些管道与闸门都是由容器自身老控制的,所以我们可以看到注入standardenginevalve等类了。

下面就从container容器的四个子容器入手,分析每一个容器是怎么样处理的:

engine容器

engine容器包含host容器,根据文章第一部分的架构图,可以知道其管理的容器是host,engine是一个接口,其标准实现类是standardengine,下面是其类结构图:

深入理解Tomcat系列之四:Engine和Host容器
深入理解Tomcat系列之四:Engine和Host容器

注意其中的addchild方法,其类型是container,但是其实际管理的就是host容器。engine容器处理请求的流程可以简化如下:

深入理解Tomcat系列之四:Engine和Host容器

在刚开始的流程图中调用了standardenginevalve的invoke方法,这个方法的具体实现如何呢?

代码清单4-1:

可以看到这个方法的任务就是选择可用的host容器处理当前的请求,选择host容器后,就调用其invoke方法,所以具体的处理就转移到了host容器。

host容器

host容器是engine容器的子容器,上面也说到host是受engine容器管理的,就是指一个虚拟主机,比如我们在访问具体jsp页面url中localhost就是一个虚拟主机,其作用是运行多个应用,并对这些应用进行管理,其子容器是context,而且一个主机还保存了主机的相关信息。host的标准实现类是standardhost,其闸门实现是standardhostvalve,下面是standardhost与standardhostvalve的类结构图:

深入理解Tomcat系列之四:Engine和Host容器
深入理解Tomcat系列之四:Engine和Host容器

host容器的处理流程可以简化如下:

深入理解Tomcat系列之四:Engine和Host容器

接着我们回到engine容器的invoke方法,下面是<code>host.getpipeline().getfirst().invoke(request, response)</code>的方法源码:

代码清单4-2:

其处理过程可以总结如下:

1. 为特定的请求url选择一个context容器

2. 把context容器绑定到线程中

3. 判断是否是一个异步请求

4. 让context去处理这个请求

5. context执行invoke方法,进入管道中,由standardcontextvalve(是contextvalve的标准实现类)处理