Web 容器与 Tomcat 核心知识总结(李号双课程笔记01-06)
Web 容器与 Tomcat 核心知识总结(李号双课程笔记)
本文整理自李号双《深入拆解 Tomcat & Jetty》专栏第 1-3 讲核心内容,聚焦 Web 容器本质、Servlet 规范及 Tomcat 架构设计,适合 Java 后端开发者夯实基础、突破技术深度。
一、课程核心定位
本课程以Tomcat、Jetty两大 Web 容器为核心,通过剖析开源系统的设计精髓,帮助开发者打通 “基础→框架→架构” 的知识链路,解决 “仅会用框架、不懂底层原理” 的痛点,为成长为高级程序员 / 架构师提供技术支撑。
二、Web 容器基础:是什么与为什么
1. Web 容器的由来(技术演进视角)
Web 容器的出现是为了解决 “静态 Web→动态 Web” 的需求升级,具体演进路径如下表:
| 阶段 | 核心技术 | 局限性 | 解决方案 |
| 早期 Web | HTTP 服务器(Apache、Nginx) | 仅能返回静态 HTML,无交互能力 | - |
| 动态需求兴起 | Servlet 技术(服务端 Java 小程序) | Servlet 无main方法,无法独立运行 | 引入Servlet 容器(管理 Servlet 的创建、调用、销毁) |
| 易用性优化 | “HTTP 服务器 + Servlet 容器” 组合 | 简化部署流程,降低使用门槛 | 形成Web 容器(Tomcat、Jetty 的本质) |
2. Web 容器的核心定义
- 本质:“HTTP 服务器 + Servlet 容器” 的结合体,兼具两大能力:
-
- 解析 HTTP 协议(接收浏览器请求、返回响应结果);
-
- 管理 Servlet 生命周期(实例化、调用service方法、销毁)。
- 轻量级 vs 重量级对比:
| 类型 | 代表产品 | 核心能力 | 适用场景 |
| 轻量级 | Tomcat、Jetty | 仅含 Servlet 容器,支持 Servlet 4.0 规范 | 微服务架构(Spring Boot 默认嵌入式容器) |
| 重量级 | JBoss、WebLogic | 含 Servlet 容器 + EJB 容器,支持完整 Java EE 规范 | 传统单体应用(需复杂企业级特性) |
- 微服务适配性:轻量级容器因低资源消耗(内存 / CPU 占用少)、支持嵌入式启动(应用启动容器,而非容器部署应用),成为微服务架构的首选。
三、Servlet 规范:Web 容器的 “通信协议”
Servlet 规范是 Web 容器(如 Tomcat)与业务类(Servlet)的交互标准,核心解决 “HTTP 服务器与业务逻辑解耦” 的问题。
1. 核心组件与作用
(1)Servlet 接口:业务类的 “标准模板”
Servlet 接口定义了 5 个核心方法,强制规范业务类的实现逻辑:
public interface Servlet {
// 初始化(加载资源,仅调用1次)
void init(ServletConfig config) throws ServletException;
// 获取初始化参数(如web.xml中配置的参数)
ServletConfig getServletConfig();
// 核心方法:处理请求(每次请求调用1次)
void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
// 获取Servlet信息(如版本、作者)
String getServletInfo();
// 销毁(释放资源,仅调用1次)
void destroy();
}
- 关键方法:service()是业务逻辑的核心实现处,其中:
-
- ServletRequest:封装请求信息(如 URL 路径、请求参数、Cookie、HTTP 头);
-
- ServletResponse:封装响应信息(如返回 HTML 内容、设置响应头、指定编码)。
- 简化实现方式:通过继承抽象类减少重复代码:
-
- GenericServlet:实现 Servlet 接口的通用逻辑(如getServletConfig()),仅需子类重写service();
-
- HttpServlet:HTTP 场景专用抽象类(继承GenericServlet),将service()方法拆分为doGet()/doPost(),开发者仅需重写对应方法(无需处理请求方法判断)。
(2)Servlet 容器:规范的 “执行者”
- 核心职责:
-
- 加载 Web 应用(解析web.xml或注解配置);
-
- 管理 Servlet 生命周期(根据请求创建 Servlet 实例、调用方法);
-
- 转发请求(将 HTTP 请求传递给对应的 Servlet 处理)。
- 解耦逻辑:HTTP 服务器不直接调用业务类,而是将请求交给 Servlet 容器,容器通过 Servlet 接口调用业务逻辑 —— 避免服务器代码与业务代码耦合(新增业务无需修改服务器代码)。
(3)Web 应用目录结构:规范的 “部署格式”
Web 应用需按固定结构部署,确保容器能识别并加载 Servlet,标准结构如下:
MyWebApp/ # Web应用根目录(访问时需指定此名称)
├─ WEB-INF/ # 核心配置目录(外界无法直接访问,安全隔离)
│ ├─ web.xml # 配置文件(Servlet映射、Filter、Listener、初始化参数)
│ ├─ classes/ # 业务类目录(Servlet类、工具类、实体类等)
│ └─ lib/ # 依赖JAR包目录(如Servlet API、Spring、MyBatis等)
└─ META-INF/ # 应用元信息目录(如MANIFEST.MF,描述应用信息)
(4)扩展机制:Filter 与 Listener
Servlet 规范提供两种扩展机制,满足个性化需求:
- Filter(过滤器):
-
- 作用:统一处理请求 / 响应(如权限校验、字符编码设置、日志记录);
-
- 原理:通过FilterChain链式调用,多个 Filter 按配置顺序执行;
-
- 场景:登录校验(未登录则跳转登录页)、统一设置UTF-8编码。
- Listener(监听器):
-
- 作用:监听容器事件(如 Web 应用启动 / 停止、Session 创建 / 销毁),触发自定义逻辑;
-
- 场景:Spring 框架通过ContextLoaderListener,在 Web 应用启动时初始化 Spring 容器。
2. 手动实现 Servlet:从 0 到 1 实践
以 “返回 Hello Servlet” 为例,演示 Servlet 的开发、编译、部署全流程:
步骤 1:编写 Servlet 类(继承 HttpServlet)
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
// 注解配置:指定Servlet映射路径(Servlet 3.0+支持,无需web.xml)
@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {
// 处理GET请求
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 设置响应内容类型及编码(避免中文乱码)
resp.setContentType("text/html;charset=utf-8");
// 获取输出流,返回HTML内容
PrintWriter out = resp.getWriter();
out.println("<h1>Hello Servlet!</h1>");
out.println("<p>这是手动实现的第一个Servlet</p>");
}
}
步骤 2:编译 Servlet 类
- 依赖:需引入 Tomcat 的lib/servlet-api.jar(提供 Servlet 接口);
- 编译命令(Windows/Linux 通用):
javac -cp ./servlet-api.jar MyServlet.java
- 结果:生成MyServlet.class字节码文件。
步骤 3:部署到 Tomcat
- 在 Tomcat 的webapps目录下,创建MyWebApp/WEB-INF/classes目录;
- 将MyServlet.class放入classes目录;
- (注解方式无需此步)若用web.xml配置,需在WEB-INF下创建web.xml,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0">
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/myServlet</url-pattern>
</servlet-mapping>
</web-app>
步骤 4:启动与访问
- 启动 Tomcat:执行Tomcat/bin/startup.bat(Windows)或startup.sh(Linux);
- 预期结果:页面显示 “Hello Servlet!” 及后续内容。
四、Tomcat 架构:核心组件与工作原理
Tomcat 的设计围绕 “处理请求” 与 “管理 Servlet” 两大核心,通过模块化拆分实现 “高内聚、低耦合”。
1. 总体架构:从顶层到核心
Tomcat 的顶层组件层级关系如下,每个组件各司其职:
Server(Tomcat实例) → Service(服务单元) → [多个Connector(连接器) + 1个Container(容器)]
- Server:整个 Tomcat 实例,可包含多个 Service(如同时提供 HTTP 和 AJP 服务);
- Service:逻辑上的 “服务单元”,仅负责将 Connector 与 Container 绑定(无实际业务逻辑);
- Connector:对外 “通信窗口”—— 处理 Socket 连接、解析 HTTP/AJP 协议,将字节流转为ServletRequest;
- Container:对内 “业务处理器”—— 管理 Servlet,处理请求并生成ServletResponse。
2. Connector:连接器的 “三层架构”
Connector 通过 3 个组件实现 “通信→协议解析→请求转换” 的全流程,屏蔽 I/O 模型与协议的差异,确保 Container 无需关注底层通信细节:
| 组件 | 核心职责 | 关键特性 |
| EndPoint | 底层通信(TCP/IP 协议) | 1. 监听指定端口(如 8080)、接收 Socket 连接;2. 支持多种 I/O 模型(NIO、NIO2、APR);3. 含 Acceptor(监听连接)、SocketProcessor(处理连接,提交线程池)。 |
| Processor | 应用层协议解析 | 1. 解析 HTTP/AJP 协议(如解析请求行、请求头);2. 将字节流转为 Tomcat 内部Request对象;3. 支持多种协议(HTTP/1.1、HTTP2、AJP)。 |
| Adapter(CoyoteAdapter) | 请求格式转换 | 1. 将 Tomcat 内部Request转为 Servlet 规范的ServletRequest;2. 调用 Container 的service方法处理请求;3. 适配器模式的典型应用(解决 Connector 与 Container 的接口差异)。 |
3. Container:容器的 “四层结构”
Container 采用组合模式,通过四层容器实现 “精细化管理 Servlet”,支持多虚拟主机、多 Web 应用的部署:
Engine(引擎) → Host(虚拟主机) → Context(Web应用) → Wrapper(Servlet)
- 各层容器作用:
| 容器层级 | 核心作用 | 示例 |
| Engine | 顶级容器,管理多个 Host(一个 Service 对应一个 Engine) | Tomcat 默认 Engine:Catalina |
| Host | 虚拟主机(对应一个域名),管理多个 Context | 域名manage.shopping.com、user.shopping.com |
| Context | Web 应用(对应一个 Web 应用目录),管理多个 Wrapper | 应用/order(订单系统)、/search(搜索系统) |
| Wrapper | 最小容器,对应一个 Servlet(每个 Servlet 对应一个 Wrapper) | MyServlet、LoginServlet |
4. 请求处理全流程
以 “用户访问http://user.shopping.com:8080/order/buy” 为例,Tomcat 的请求处理流程如下:
- 定位容器:Mapper 组件通过 URL 解析,定位到目标 Wrapper:
-
- 端口8080→确定 Connector(HTTP 连接器)→确定 Service→确定 Engine;
-
- 域名user.shopping.com→确定 Host(user对应的 Host 容器);
-
- 路径/order→确定 Context(order对应的 Web 应用);
-
- 路径/buy→确定 Wrapper(buy对应的 Servlet)。
- 链式调用(Pipeline-Valve):
-
- 每个容器(Engine/Host/Context/Wrapper)都有一个Pipeline(管道),Pipeline中维护Valve(阀门)链表;
-
- Valve分为两类:
-
-
- 自定义 Valve:实现通用逻辑(如日志记录、权限校验);
-
-
-
- BasicValve:每个 Pipeline 的 “收尾 Valve”,负责调用下一层容器的 Pipeline。
-
-
- 调用顺序:Engine Pipeline → Host Pipeline → Context Pipeline → Wrapper Pipeline。
- 最终处理:Wrapper 的 BasicValve 创建 Filter 链,调用 Servlet 的service方法,生成响应并返回给浏览器。
五、Web 容器学习路径:打好基础是关键
课程强调 “先夯实基础,再深入源码”,核心基础分为三类,缺一不可:
1. 操作系统基础(核心)
- 必学内容:
-
- 进程 / 线程、内核空间 / 用户空间、线程同步;
-
- I/O 模型(阻塞 / 非阻塞、同步 / 异步);
-
- 网络协议(TCP/IP、UDP、HTTP、OSI 七层模型);
-
- 虚拟内存、内存分配。
- 推荐书籍:《UNIX 环境高级编程》(APUE)。
2. Java 语言基础(核心)
- 必学内容:
-
- 面向对象(封装、继承、多态、接口、抽象类);
-
- Java I/O(字节流 / 字符流、NIO);
-
- 多线程(线程池、并发容器、原子类、锁机制);
-
- JVM(类加载机制、内存模型、GC 原理、本地内存);
-
- Java 网络编程(BIO、NIO、AIO)。
- 推荐书籍:
-
- 《Java 核心技术》(卷 1 / 卷 2);
-
- 《深入理解 Java 虚拟机》(周志明);
-
- 《Java 并发编程实战》。
3. Java Web 基础(核心)
- 必学内容:
-
- Servlet 规范(Servlet、Filter、Listener);
-
- Web 应用工作原理(请求 / 响应流程);
-
- 设计模式(适配器、责任链、组合、模板方法);
-
- 关键认知:Web 框架(如 Spring)是对 Servlet 的封装,理解 Servlet 容器是掌握框架原理的前提。
六、核心思考题与答案
思考题:Tomcat 的 Context 与 ServletContext、Spring 的 ApplicationContext 有什么区别?
| 概念 | 归属 | 核心作用 | 生命周期 |
| Tomcat Context | Tomcat 容器组件 | 管理 Web 应用的 Servlet、资源(如 JSP、静态文件),是 Tomcat 内部的容器实例 | 与 Web 应用一致(部署时创建,卸载时销毁) |
| ServletContext | Servlet 规范接口 | 提供 Web 应用的全局配置(如获取初始化参数、共享全局数据、访问资源),是 Web 应用的 “全局上下文” | 与 Web 应用一致(Web 应用启动时创建,停止时销毁) |
| Spring ApplicationContext | Spring 框架容器 | 管理 Spring Bean 的创建、依赖注入、生命周期,是 Spring 应用的 “核心上下文” | 由 Spring 监听器(如ContextLoaderListener)触发创建,Web 应用停止时销毁 |
- 关联关系:Spring 的ApplicationContext依赖ServletContext—— 通过ServletContext获取 Web 应用的配置信息,在 Web 应用启动时初始化。
七、总结
- Web 容器本质:Tomcat/Jetty 是 “HTTP 服务器 + Servlet 容器” 的结合体,核心解决 “动态请求处理” 与 “微服务适配”;
- Servlet 规范是基石:定义了容器与业务类的交互标准,Filter/Listener 提供灵活的扩展能力;
- Tomcat 架构精髓:通过 Connector 与 Container 解耦 “通信” 与 “业务”,通过分层组件实现高灵活性与可扩展性;
- 学习建议:先掌握 OS/Java/Web 基础,再从 “手动实现 Servlet” 入手,逐步深入 Tomcat 源码,理解设计模式的实际应用 —— 只有打通底层原理,才能在框架迭代中保持技术竞争力。
转载说明:本文整理自李号双《深入拆解 Tomcat & Jetty》专栏,如需转载,请注明原文出处及作者。
更多推荐
所有评论(0)