Tomcat 容器(Container)体系源码剖析

在这里插入图片描述

1. 引言

在上一章中,我们剖析了 Connector(连接器),它负责接收网络请求并解析协议。
但真正决定请求如何被分发、哪个 Servlet 来处理的,是 Tomcat 的 容器(Container)

Tomcat 使用 分层容器模型,并结合 Pipeline-Valve 责任链模式,实现了灵活的请求处理机制。


2. 容器体系结构

Tomcat 的 Container 体系分为四层:

  1. Engine

    • 一个 Service 下只能有一个 Engine
    • 代表整个 Servlet 引擎
    • 管理多个虚拟主机(Host)
  2. Host

    • 代表一个虚拟主机(域名绑定)
    • 一个 Engine 下可以有多个 Host
  3. Context

    • 代表一个 Web 应用(webapps/ 下的项目)
    • 负责加载 web.xml 配置
  4. Wrapper

    • 代表单个 Servlet
    • 负责 Servlet 的生命周期管理(init、service、destroy)

👉 结构图:

Engine
 └── Host
      └── Context
           └── Wrapper (Servlet)

3. 请求流转机制

请求从 Connector 进入后,会进入 Container 层级:

Connector → Engine → Host → Context → Wrapper → Servlet

例子:访问 http://localhost:8080/demo/hello

  1. Engine:定位默认 Engine
  2. Host:根据 localhost 定位 Host
  3. Context:根据 /demo 定位应用
  4. Wrapper:根据 /hello 映射到某个 Servlet

4. Pipeline-Valve 机制

Tomcat 使用 责任链模式 来实现请求处理。

  • Pipeline:管道,维护多个 Valve(阀门)
  • Valve:具体的处理节点,可以插入过滤逻辑
  • StandardPipeline:默认实现
  • StandardValve:容器的核心处理逻辑

执行流程:

Pipeline → Valve1 → Valve2 → ... → StandardValve → 下级容器

这样设计的好处:

  • 方便扩展(例如 AccessLogValve、ErrorReportValve)
  • 支持灵活的拦截处理(类似 Spring 的拦截器链)

5. 核心源码解析

(1) Container 接口

Tomcat 的四个容器(Engine、Host、Context、Wrapper)都实现了 org.apache.catalina.Container 接口:

public interface Container extends Lifecycle {
    String getName();
    Pipeline getPipeline();
    void addChild(Container child);
    Container findChild(String name);
}
  • addChild:添加子容器
  • findChild:根据名称查找子容器
  • getPipeline:获取当前容器的 Pipeline

(2) Engine 实现

public class StandardEngine extends ContainerBase implements Engine {
    @Override
    public void startInternal() {
        // 启动所有子 Host 容器
        for (Container child : findChildren()) {
            child.start();
        }
    }
}

(3) Host 实现

public class StandardHost extends ContainerBase implements Host {
    @Override
    protected void startInternal() {
        // 加载 Context(Web 应用)
        deployApps();
    }
}

(4) Context 实现

public class StandardContext extends ContainerBase implements Context {
    @Override
    protected void startInternal() {
        // 解析 web.xml,加载 Servlet、Filter、Listener
        loadOnStartup(findChildren());
    }
}

(5) Wrapper 实现

public class StandardWrapper extends ContainerBase implements Wrapper {
    @Override
    public Servlet loadServlet() {
        // 通过反射创建 Servlet 实例
        return (Servlet) instanceManager.newInstance(servletClass);
    }
}

(6) Pipeline 与 Valve

Pipeline 的默认实现:

public class StandardPipeline implements Pipeline {
    protected Valve basic;
    protected List<Valve> valves = new ArrayList<>();

    @Override
    public void addValve(Valve valve) {
        valves.add(valve);
    }

    @Override
    public Valve getBasic() {
        return basic; // 最终调用 StandardValve
    }
}

6. 请求处理流程源码追踪

以 Context 为例:

public class StandardContextValve extends ValveBase {
    @Override
    public void invoke(Request request, Response response) {
        // 定位目标 Wrapper(Servlet)
        Wrapper wrapper = request.getWrapper();
        wrapper.getPipeline().getFirst().invoke(request, response);
    }
}

最终进入 Wrapper → Servlet.service()

public class StandardWrapperValve extends ValveBase {
    @Override
    public void invoke(Request request, Response response) {
        // 调用 Servlet 的 service 方法
        servlet.service(request, response);
    }
}

7. 配置与应用

server.xml 中定义容器:

<Engine name="Catalina" defaultHost="localhost">
    <Host name="localhost" appBase="webapps">
        <Context path="/demo" docBase="demo"/>
    </Host>
</Engine>

8. 总结

在本篇中,我们深入剖析了 Tomcat 容器体系:

  • 四层结构:Engine → Host → Context → Wrapper
  • 请求流转:逐层匹配,最终定位 Servlet
  • Pipeline-Valve 机制:责任链模式,支持扩展
  • 核心源码:StandardEngine、StandardHost、StandardContext、StandardWrapper

容器是 Tomcat 的请求调度核心,理解它的分层和 Pipeline 机制,才能真正掌握请求是如何一步步路由到 Servlet 的。


Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐