在 Java Web 开发中,Tomcat 是最常用的 Servlet 容器之一。对于许多传统部署的系统(非 Spring Boot 内嵌方式),我们经常会将多个 WAR 包部署到同一个 Tomcat 实例下,并通过不同的域名和路径访问不同的子系统。那么,一个 HTTP 请求从客户端发起,到最后返回响应,在 Tomcat 中到底发生了什么?本文将结合 Tomcat 的核心组件结构,深入剖析一次完整请求的处理流程。
一、Tomcat 的核心组件结构及对应关系
Tomcat 采用分层组件架构,每一层都有清晰的职责,主要组件如下:
Tomcat 组件 | 角色类比 | 实际职责 |
---|---|---|
Server | 整个 Tomcat 实例 | 全局生命周期管理 |
Service | 服务容器 | 管理 Connector 和 Engine |
Connector | 网络监听端口 | 接收 HTTP 请求并解析为 Request 对象 |
Engine | 中央调度器 | 接收 Request,根据 Host 分发请求 |
Host | 虚拟机 / 容器 | 虚拟主机(按域名隔离 Web 应用) |
Context | 一个 Web 应用(WAR 包) | 路径映射,如 /crm 对应一个 WAR 包 |
Wrapper | 一个 Servlet | 请求的最终处理者,如 HelloServlet |
Valve/Realm/Cluster | 附加组件 | 日志、安全、集群等 |
举例说明
假设你部署了如下结构的应用:
/opt/tomcat/webapps/
├── crm.war → 客户关系管理系统
├── hr.war → 人力资源系统
├── billing.war → 计费系统
这些 WAR 包在启动时会被 Tomcat 解压为 Context,例如 /crm
、/hr
、/billing
。你还可以在 server.xml
中配置不同的 Host 来支持多租户或多域名。
二、一次完整请求在 Tomcat 中的处理链路
示例请求:
GET http://crm.example.com/crm/user/list
我们逐步来看这个请求是如何在 Tomcat 中流转的。
步骤 1:客户端发起请求
- 协议:HTTP
- Host Header:
crm.example.com
- 路径:
/crm/user/list
步骤 2:Connector 接收请求
Tomcat 的 Connector(由 Coyote 实现)监听配置端口(如 8080),接收 Socket 连接,解析 HTTP 报文,构造 Tomcat 的 Request
对象,并交给 Engine。
步骤 3:Engine 查找 Host
Engine 是请求的调度核心,它读取请求的 Host Header,比如 crm.example.com
,在配置的 Host 列表中查找对应 Host(如 HostA)。找不到则使用默认 Host。
<Engine name="Catalina" defaultHost="crm.example.com">
<Host name="crm.example.com" appBase="webapps/crm">
...
</Host>
</Engine>
步骤 4:Host 查找 Context(Web 应用)
Host 拿到路径 /crm/user/list
,会提取 Context Path 部分 /crm
,在部署的 Web 应用中查找是否存在 Context /crm
,通常对应 /webapps/crm/
。
步骤 5:Context 查找 Servlet(Wrapper)
Context 处理剩下的路径 /user/list
,根据 web.xml 或注解映射匹配到对应 Servlet,例如 /user/*
映射到 UserServlet
。
如果是 Spring 应用,这时 DispatcherServlet 会拦截 /
,由 Spring MVC 的 HandlerMapping 找到 Controller 方法。
步骤 6:Servlet 执行并返回响应
Servlet 的 service()
方法被调用,处理逻辑后通过 Tomcat 的 Response 对象写出响应内容。
步骤 7:Response 回传给客户端
Response 对象中的数据通过 Connector 写回 socket 连接,完成本次请求处理。
三、整体流程图(文字版)
[客户端请求 http://crm.example.com/crm/user/list]
↓
[Tomcat Connector 接收请求]
↓
[Engine 根据 Host header 选择 HostA]
↓
[HostA 查找 Context /crm]
↓
[Context 查找匹配的 Servlet]
↓
[DispatcherServlet → Controller 方法 → JSON 返回]
↓
[Response 写回 → Connector 输出 → 客户端]
四、总结
一个请求从浏览器发送到 Tomcat 后,会经过:Connector → Engine → Host → Context → Servlet → Response 的完整链路。
- Host 类似一台虚拟机或容器,按域名进行隔离;
- Context 是一个具体的 Web 应用,通常是一个 WAR 包;
- Servlet 是 Web 应用中具体的请求处理器;
- 所有组件的调度由 Engine 统一完成。
掌握 Tomcat 的核心结构和请求处理链路,不仅有助于调试生产问题,更能帮助我们深入理解 Web 容器的设计思想和扩展能力。
如果你用惯了 Spring Boot 的内嵌模式,不妨重新回头审视一下传统部署的 Tomcat 架构,你会发现不少值得学习的“底层功夫”。