Servlet 与 Tomcat 的底层执行逻辑及自定义 Tomcat 实现
本文深入解析JavaWeb中Servlet与Tomcat的协作机制。Servlet作为HTTP请求处理规范,采用分层设计(Servlet接口→GenericServlet→HttpServlet→自定义实现),降低开发复杂度。Tomcat作为Servlet容器,负责请求处理的完整流程:监听端口→解析请求→匹配Servlet→调用处理→返回响应。文章还演示了如何手动实现简易Tomcat容器,包括Se
在 Java Web 技术栈中,Servlet 是处理 HTTP 请求的核心组件,而Tomcat 是运行 Servlet 的容器—— 二者的协作是 Web 应用运行的基础。本文将结合底层流程图,从 Servlet 的体系结构、Tomcat 的请求处理流程,到自定义 Tomcat 的实现,完整拆解其底层逻辑。
一、Servlet:HTTP 请求处理的规范与实现
Servlet 并非独立的 “类”,而是一套请求处理的接口规范,其设计采用 “接口 - 抽象类 - 业务实现” 的分层模式,降低了开发复杂度。

1. Servlet 接口:定义核心生命周期
Servlet是所有 Servlet 组件的根接口,它规定了组件从创建到销毁的完整生命周期方法:
public interface Servlet {
// 初始化:容器创建Servlet实例后调用,仅执行1次
void init(ServletConfig config) throws ServletException;
// 处理请求:每次客户端请求时触发,封装业务逻辑
void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
// 获取组件信息:返回Servlet的描述性内容
String getServletInfo();
// 销毁:容器回收实例前调用,用于释放资源
void destroy();
}
2. GenericServlet:简化接口实现
GenericServlet是一个抽象类,它实现了Servlet接口中除service()外的所有方法,核心作用是封装通用逻辑:
- 自动维护
ServletConfig对象,提供getInitParameter()等工具方法; - 统一处理初始化与资源释放的重复代码。
开发者只需重写service()即可实现请求处理,但该类未适配 HTTP 协议,实际开发中较少直接使用。
3. HttpServlet:适配 HTTP 协议的实现
HttpServlet继承自GenericServlet,其核心是重写service()方法,并根据 HTTP 请求的方法类型(GET/POST/PUT 等),将请求分发到对应的doXxx()方法:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
this.doGet(req, resp);
} else if (method.equals(METHOD_POST)) {
this.doPost(req, resp);
}
// 其他HTTP方法的分发逻辑
}
4. 自定义 Servlet:业务逻辑落地
实际开发中,我们只需继承HttpServlet,重写对应请求方法即可实现业务逻辑,示例如下:
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("登录成功,用户名:" + username);
}
}
二、Tomcat:Servlet 的运行容器与请求处理流程
Servlet 本身是普通 Java 类,必须依赖 Tomcat 这样的Servlet 容器才能运行。Tomcat 的核心职责是管理 Servlet 生命周期、接收请求、分发处理并返回响应,其完整流程如下:

1. 监听与接收请求
Tomcat 通过ServerSocket监听指定端口(默认 8080),由Acceptor线程接收客户端连接,再通过线程池分配工作线程处理请求(避免频繁创建线程的开销)。
2. 解析请求报文
Tomcat 将原始 HTTP 请求报文解析为HttpServletRequest对象,包含三部分核心内容:
- 请求行:请求方法(GET/POST)、URI、HTTP 版本;
- 请求头:Cookie、Content-Type 等首部字段;
- 请求体:POST 请求的表单数据、JSON 等内容。
3. 匹配 Servlet 组件
Tomcat 根据请求 URI 查询Servlet 映射表(由web.xml或@WebServlet注解配置),找到对应的 Servlet 类。若该 Servlet 实例未初始化,则调用init()方法完成初始化(仅执行一次)。
4. 调用 Servlet 处理请求
Tomcat 将HttpServletRequest和HttpServletResponse对象传入 Servlet 的service()方法,通过HttpServlet的方法分发逻辑,最终执行自定义 Servlet 中重写的doGet()/doPost()方法。
5. 生成并返回响应
自定义 Servlet 通过HttpServletResponse对象封装响应数据(响应行、响应头、响应体),Tomcat 将其转换为 HTTP 响应报文,通过 Socket 写回客户端,完成请求处理。
三、自定义 Tomcat:手动实现简易容器
基于 Tomcat 的核心逻辑,我们可以实现一个简易的 Servlet 容器,核心步骤如下:

1. 配置 Servlet 映射
定义 URI 与 Servlet 类的映射关系,模拟 Tomcat 的映射表:
private static final Map<String, Class<? extends HttpServlet>> SERVLET_MAP = new HashMap<>();
static {
SERVLET_MAP.put("/login", LoginServlet.class);
}
2. 监听端口并接收请求
创建ServerSocket监听端口,通过多线程处理客户端连接:
public static void start(int port) throws IOException {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("自定义Tomcat启动,监听端口:" + port);
while (true) {
Socket socket = serverSocket.accept(); // 阻塞等待请求
new Thread(() -> handleRequest(socket)).start(); // 多线程处理
}
}
3. 解析请求与封装对象
读取 Socket 输入流,解析请求行信息,模拟HttpServletRequest对象:
private static void handleRequest(Socket socket) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
// 解析请求行:GET /login HTTP/1.1
String requestLine = reader.readLine();
if (requestLine == null) return;
String[] parts = requestLine.split(" ");
String method = parts[0];
String uri = parts[1];
// 封装请求/响应对象
HttpServletRequest req = new MyHttpServletRequest(method, uri);
HttpServletResponse resp = new MyHttpServletResponse(socket.getOutputStream());
4. 实例化 Servlet 并调用
根据 URI 获取 Servlet 类,实例化后调用service()方法处理请求
// 获取并实例化Servlet
Class<? extends HttpServlet> servletClass = SERVLET_MAP.get(uri);
if (servletClass == null) {
resp.setStatus(404);
resp.getWriter().write("404 Not Found");
return;
}
HttpServlet servlet = servletClass.getDeclaredConstructor().newInstance();
// 调用service方法处理请求
servlet.service(req, resp);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. 封装响应对象
自定义HttpServletResponse实现,将响应数据写入 Socket 输出流:
public class MyHttpServletResponse extends HttpServletResponseWrapper {
private final OutputStream outputStream;
public MyHttpServletResponse(OutputStream outputStream) {
super(null);
this.outputStream = outputStream;
}
@Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
}
}
总结
Servlet 是 HTTP 请求处理的规范组件,通过分层设计降低了开发成本;Tomcat 作为容器,负责 Servlet 的生命周期管理与请求的 “接收 - 解析 - 分发 - 响应” 全流程;自定义 Tomcat 的核心是模拟这一流程,理解其底层逻辑能帮助我们更深入地掌握 Java Web 技术。
更多推荐



所有评论(0)