1. Servlet 容器本质解析
1.1 从 HTTP 请求到 Java 对象的旅程
当你在浏览器输入一个 URL 时,Servlet 容器就像一位专业的翻译官,默默完成了以下关键工作流程:
-
端口监听:容器启动时会在指定端口(默认8080)创建 ServerSocket,这个端口就像公司前台的电话总机。以 Tomcat 为例,其核心组件 Connector 会绑定到网络接口,等待连接请求。
-
协议解析:收到原始 HTTP 请求后,容器会逐行解析请求头、请求体,这个过程相当于把客户寄来的纸质信件(字节流)转换成标准格式的电子工单。例如:
- 解析请求行:GET /hello HTTP/1.1
- 解析 Headers:Content-Type、Cookie 等
- 处理 URL 编码和参数
-
对象封装:将解析结果包装成 HttpServletRequest 对象,这个对象就像一个包含了所有客户需求的工单文件夹。同时创建 HttpServletResponse 作为空白的回复表格。
实际案例:当访问
http://localhost:8080/hello?name=John时,容器会:
- 创建 request 对象并设置属性:method="GET", path="/hello", parameterMap=
- 初始化 response 的状态码为200,headers 为空
1.2 Servlet 生命周期管理机制
Servlet 容器对组件的管理就像工厂的流水线控制系统:
java复制// 典型生命周期(以Tomcat为例)
public class StandardWrapper {
void loadServlet() {
// 1. 类加载
Class<?> clazz = loader.loadClass(className);
// 2. 实例化(调用无参构造)
Servlet servlet = (Servlet) clazz.newInstance();
// 3. 初始化(调用init())
servlet.init(new StandardWrapperFacade(this));
// 4. 加入就绪队列
this.servlet = servlet;
}
}
关键时间点控制:
- 首次请求到达时进行初始化(可通过load-on-startup调整)
- 每个请求创建新线程调用 service() 方法
- 应用关闭时执行 destroy() 清理资源
1.3 线程模型与并发处理
Tomcat 的线程池配置就像餐厅的服务员团队:
properties复制# conf/server.xml 典型配置
<Connector
executor="tomcatThreadPool"
port="8080"
maxThreads="200" # 最大服务员数量
minSpareThreads="10" # 常备服务员
acceptCount="100" # 等候区座位数
/>
工作流程:
- 请求到达时,检查是否有空闲线程(服务员)
- 若无空闲且未达maxThreads,创建新线程
- 若已达上限,请求进入等待队列(acceptCount)
- 请求超时(默认20秒)返回503
生产环境建议:maxThreads = (CPU核心数 * 2) + 空闲线程缓冲
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 主流 Servlet 容器深度对比
2.1 技术架构差异
| 容器 | 架构特点 | IO模型 | 类加载机制 |
|---|---|---|---|
| Tomcat | 模块化设计(Catalina/Coyote/Jasper) | NIO/APR | 父子委派 + 热部署 |
| Jetty | 轻量级组件化 | 异步IO | 自定义类加载体系 |
| Undertow | 基于XNIO框架 |
