目录
Tomcat系统架构(下):容器
/  

Tomcat系统架构(下):容器

Tomcat 设计了 4 种容器,分别是 Engine、Host、Context 和 Wrapper。这 4 种容器不是平行关系,而是父子关系。
null

  • Context 表示一个 Web 应用程序
  • Wrapper 表示一个 Servlet,一个 Web 应用下可能有多个 servlet
  • Host 代表的是一个虚拟主机,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可以部署多个 Web 应用程序
  • Engine 表示引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine。

再通过 Tomcat 的 server.xml 配置文件来加深对 Tomcat 容器的理解。

null

可以发现 Engine, Host, Context, Wrapper, 是嵌套关系。一个 Tomcat 实例包含一个 Engine, 一个 Engine 包含多个 Host, 以此类推。

可以这些容器具有父子关系,形成一个树形结构,Tomcat 通过组合模式进行管理这些容器。具体实现方法是,所有容器组件都实现了 Container 接口。
因此组合模式可以使得用户对单容器对象和组合容器对象的使用具有一致性。这里单容器对象指的是最底层的 Wrapper,组合容器对象指的是上面的 Context、Host 或者 Engine。Container 接口定义如下:


public interface Container extends Lifecycle {
    public void setName(String name);
    public Container getParent();
    public void setParent(Container container);
    public void addChild(Container child);
    public void removeChild(Container child);
    public Container findChild(String name);
}

请求定位 Servlet 的过程
Tomcat 通过 Mapper 组件,来确定请求是由哪个 Wrapper 容器的 Servlet 进行处理。Mapper 组件里保存了 Web 应用的配置信息,其实就是容器组件与访问路径的映射关系。

null

可以看到 Tomcat 通过一层一层的父子容器找到某一个 Servlet 来处理请求。需要注意的是并不是说只有 Servlet 才会去处理请求,实际上这个查找路径上的父子容器都会对请求做一些处理。这个过程是通过 Pipeline-Valve 管道实现的。

Pipeline-Valve 是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将再调用下一个处理者继续处理。


public interface Valve {
  public Valve getNext();
  public void setNext(Valve valve);
  public void invoke(Request request, Response response)
}

public interface Pipeline extends Contained {
  public void addValve(Valve valve);
  public Valve getBasic();
  public void setBasic(Valve valve);
  public Valve getFirst();
}

Pipeline 中维护了 Valve 链表,整个调用链的触发是 Valve 来完成的,Valve 完成自己的处理后,调用 getNext.invoke 来触发下一个 Valve 调用。BasicValve 处于 Valve 链表的末端,它是 Pipeline 中必不可少的一个 Valve,负责调用下层容器的 Pipeline 里的第一个 Valve。

null

整个调用过程由连接器中的 Adapter 触发的,它会调用 Engine 的第一个 Valve:

connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
  • Tomcat 内的 Context 组件跟 Servlet 规范中的 ServletContext 接口有什么区别?跟 Spring 中的 ApplicationContext 又有什么关系?

Servlet 规范中 ServletContext 表示 Web 应用的上下文环境,而 Web 应用对应 Tomcat 的概念是 Context。所以从设计上,ServletContext 自然会成为 Context 具体实现的一个成员变量,Tomcat 内部也是这样实现的。
ServletContext 对应 Tomcat 实现的是org.apache.catalina.core.ApplicationContext
Context 容器对应 Tomcat 实现的是 org.apache.catalina.core.StandardContext
ApplicationContext 是 StandardContext 的一个成员变量。

image.png

Tomcat 启动过程中,Spring 的org.springframework.web.context.ContextLoaderListener会监听到容器初始化事件,在contextInitialized方法中,Spring 会初始化全局的根容器 ApplicationContext ,初始化完毕后,Spring 将其存储到 ServletContext 中。

image.png

总而言之,Servlet 规范中 ServletContext 是 Tomcat 的 Context 实现的一个成员变量,而 Spring 的 ApplicationContext 是 Servlet 规范中 ServletContext 的一个属性(Attribute)。


道路且长,行则将至。