Java Web 底层解析:Servlet 执行流程、Tomcat 工作原理与自定义 Tomcat 实现

引言:

[一、Servlet 执行流程:从接口到自定义实现](#一、Servlet 执行流程:从接口到自定义实现)

[1.1 Servlet 核心体系结构](#1.1 Servlet 核心体系结构)

[1.2 Servlet 生命周期(核心方法执行流程)](#1.2 Servlet 生命周期(核心方法执行流程))

[1.3 自定义 Servlet 示例](#1.3 自定义 Servlet 示例)

1.4Servlet执行流程图

[二、Tomcat 执行流程:从 HTTP 请求到 Servlet 响应](#二、Tomcat 执行流程:从 HTTP 请求到 Servlet 响应)

[2.1 请求接收与解析(基于 Socket)](#2.1 请求接收与解析(基于 Socket))

[2.2 请求分发与 Servlet 调用](#2.2 请求分发与 Servlet 调用)

[2.3 响应返回](#2.3 响应返回)

[2.4 Tomcat 的 I/O 模型(BIO 到 NIO)](#2.4 Tomcat 的 I/O 模型(BIO 到 NIO))

2.5Tomcat执行流程图

[三、自定义简易 Tomcat:手动实现核心流程](#三、自定义简易 Tomcat:手动实现核心流程)

[3.1 核心组件定义](#3.1 核心组件定义)

[3.2 自定义 Tomcat 实现](#3.2 自定义 Tomcat 实现)

[3.3 自定义 Servlet 实现](#3.3 自定义 Servlet 实现)

[3.4 运行效果](#3.4 运行效果)

3.5自定义Tomcat图

四、总结


引言:

在 Java Web 开发中,Servlet是处理 HTTP 请求的核心组件,而 Tomcat是承载 Servlet 运行的 Web 容器。本文将从「Servlet 执行流程」「Tomcat 工作原理」「自定义简易 Tomcat 实现」三个维度,深入解析 Java Web 的底层逻辑。

一、Servlet 执行流程:从接口到自定义实现

1.1 Servlet 核心体系结构

Servlet 的核心是 `Servlet` 接口,其体系结构如下:

  1. `Servlet` 接口:定义了 Servlet 的生命周期方法(`init()`、`service()`、`destroy()` 等);
  2. `GenericServlet` 抽象类:实现了 `Servlet` 接口的大部分方法(除 `service()` 外);
  3. `HttpServlet` 抽象类:继承 `GenericServlet`,重写了 `service()` 方法,适配 HTTP 请求(将请求分发到 `doGet()`、`doPost()` 等方法);
  4. 自定义 Servlet:继承 `HttpServlet`,重写 `doGet()`/`doPost()` 实现具体业务逻辑。

1.2 Servlet 生命周期(核心方法执行流程)

Servlet 的生命周期由 Web 容器(如 Tomcat)管理,核心流程为:

  1. 初始化(`init()`):容器启动时(或首次请求时)调用 `init()`,初始化 Servlet 配置(`ServletConfig`);
  2. 处理请求(`service()`):每次请求到来时,容器调用 `service()`,`HttpServlet` 会根据请求方式(GET/POST)分发到对应的 `doGet()`/`doPost()`;
  3. 销毁(`destroy()`):容器关闭时调用 `destroy()`,释放 Servlet 资源。

1.3 自定义 Servlet 示例

java 复制代码
// 自定义Servlet,继承HttpServlet

public class MyServlet extends HttpServlet {

// 初始化方法

@Override

public void init(ServletConfig config) throws ServletException {

super.init(config);

System.out.println("MyServlet初始化完成");

}

// 处理GET请求

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

resp.getWriter().write("Hello Servlet!");

}

// 销毁方法

@Override

public void destroy() {

System.out.println("MyServlet销毁");

}

}

1.4Servlet执行流程图


二、Tomcat 执行流程:从 HTTP 请求到 Servlet 响应

Tomcat 是 Web 容器,负责接收 HTTP 请求、解析请求、调用 Servlet、返回响应。其核心执行流程如下:

2.1 请求接收与解析(基于 Socket)

  1. Socket 监听:Tomcat 启动后,通过 `ServerSocket` 监听指定端口(默认 8080);

  2. 请求接收:当 HTTP 请求到达端口时,Tomcat 建立 Socket 连接,打开输入流读取请求数据;

  3. 请求解析:解析请求头(如请求方式、URL、参数等),将请求封装为 `HttpServletRequest` 对象。

2.2 请求分发与 Servlet 调用

  1. 匹配 Servlet:Tomcat 通过 `web.xml` 或注解(如 `@WebServlet`)匹配 URL 对应的 Servlet;
  2. 反射实例化:通过反射创建 Servlet 对象(仅首次请求时创建),调用 `init()` 初始化;
  3. 调用业务方法:调用 Servlet 的 `service()` 方法,分发到 `doGet()`/`doPost()` 处理请求。

2.3 响应返回

  1. 装响应:Servlet 处理完请求后,将结果写入 `HttpServletResponse` 对象;
  2. 返回响应:Tomcat 将 `HttpServletResponse` 转换为 HTTP 响应报文,通过 Socket 输出流返回给客户端;
  3. 资源释放:关闭 Socket 连接(或复用连接)。

2.4 Tomcat 的 I/O 模型(BIO 到 NIO)

早期 Tomcat 使用 BIO(阻塞式 I/O):

  1. 特点:每个请求对应一个线程,无请求时线程阻塞;
  2. 缺点:高并发下线程资源耗尽,性能低。
  3. 现代 Tomcat 采用 NIO(非阻塞式 I/O):
  4. 特点:基于多路复用器,一个线程管理多个连接,无请求时线程不阻塞;
  5. 优势:高并发下性能更稳定。

2.5Tomcat执行流程图


三、自定义简易 Tomcat:手动实现核心流程

我们可以基于 Socket + 反射 + 线程池,实现一个简易版 Tomcat,核心功能是接收 HTTP 请求、调用 Servlet、返回响应。

3.1 核心组件定义

  • Servlet 接口(模拟标准 Servlet)
java 复制代码
public interface Servlet {

void init();

void service(Request request, Response response);

void destroy();

}
  • Request/Response 封装类
java 复制代码
// 请求封装类

public class Request {

private String method; // 请求方式(GET/POST)

private String url; // 请求URL

// 构造方法:解析Socket输入流得到method和url

public Request(InputStream is) {

// 省略解析逻辑

}

// getter方法

}

// 响应封装类

public class Response {

private OutputStream os;

public Response(OutputStream os) {

this.os = os;

}

// 向客户端写响应

public void write(String content) throws IOException {

String response = "HTTP/1.1 200 OK\r\n" +

"Content-Type: text/html\r\n" +

"Content-Length: " + content.getBytes().length + "\r\n" +

"\r\n" + content;

os.write(response.getBytes());

}

}

3.2 自定义 Tomcat 实现

java 复制代码
import java.net.ServerSocket;

import java.net.Socket;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class CustomTomcat {

private int port;

private ExecutorService threadPool; // 线程池处理请求

public CustomTomcat(int port) {

this.port = port;

this.threadPool = Executors.newFixedThreadPool(10); // 固定线程池

}

// 启动Tomcat

public void start() throws Exception {

ServerSocket serverSocket = new ServerSocket(port);

System.out.println("自定义Tomcat启动,监听端口:" + port);

while (true) {

Socket socket = serverSocket.accept(); // 阻塞监听请求

// 提交请求到线程池处理

threadPool.execute(() -> handleRequest(socket));

}

}

// 处理请求

private void handleRequest(Socket socket) {

try {

// 1. 封装Request和Response

Request request = new Request(socket.getInputStream());

Response response = new Response(socket.getOutputStream());

// 2. 匹配Servlet(模拟URL映射:/myServlet对应MyServlet)

if ("/myServlet".equals(request.getUrl())) {

Servlet servlet = new MyServlet();

servlet.init();

servlet.service(request, response);

servlet.destroy();

} else {

response.write("404 Not Found");

}

// 3. 关闭资源

socket.close();

} catch (Exception e) {

e.printStackTrace();

}

}

// 主方法启动

public static void main(String[] args) throws Exception {

new CustomTomcat(8080).start();

}

}

3.3 自定义 Servlet 实现

java 复制代码
public class MyServlet implements Servlet {

@Override

public void init() {

System.out.println("MyServlet初始化");

}

@Override

public void service(Request request, Response response) throws IOException {

response.write("Hello Custom Tomcat!");

}

@Override

public void destroy() {

System.out.println("MyServlet销毁");

}

}

3.4 运行效果

启动 `CustomTomcat` 后,在浏览器访问 `http://localhost:8080/myServlet`,即可看到响应内容 `Hello Custom Tomcat!`。

3.5自定义Tomcat图


四、总结

  1. Servlet 是核心:通过 `Servlet` 接口定义生命周期,`HttpServlet` 适配 HTTP 请求,自定义 Servlet 实现业务逻辑;
  2. Tomcat 是容器:负责请求接收、解析、Servlet 调用、响应返回,其 I/O 模型从 BIO 演进到 NIO 以支撑高并发;
  3. 自定义 Tomcat 核心:基于 Socket 监听请求,通过反射实例化 Servlet,线程池处理并发,是理解 Web 容器底层的最佳实践。

掌握这些底层逻辑,能帮助你更深入地理解 Java Web 框架(如 SpringMVC)的运行机制,为后续学习分布式、微服务奠定基础。

相关推荐
敲敲了个代码5 小时前
从硬编码到 Schema 推断:前端表单开发的工程化转型
前端·javascript·vue.js·学习·面试·职场和发展·前端框架
cike_y5 小时前
Mybatis之解析配置优化
java·开发语言·tomcat·mybatis·安全开发
是一个Bug6 小时前
Java基础50道经典面试题(四)
java·windows·python
dly_blog6 小时前
Vue 响应式陷阱与解决方案(第19节)
前端·javascript·vue.js
Slow菜鸟6 小时前
Java基础架构设计(三)| 通用响应与异常处理(分布式应用通用方案)
java·开发语言
消失的旧时光-19437 小时前
401 自动刷新 Token 的完整架构设计(Dio 实战版)
开发语言·前端·javascript
我是Superman丶7 小时前
《Spring WebFlux 实战:基于 SSE 实现多类型事件流(支持聊天消息、元数据与控制指令混合传输)》
java
console.log('npc')7 小时前
Table,vue3在父组件调用子组件columns列的方法展示弹窗文件预览效果
前端·javascript·vue.js
廋到被风吹走7 小时前
【Spring】常用注解分类整理
java·后端·spring
用户47949283569157 小时前
React Hooks 的“天条”:为啥绝对不能写在 if 语句里?
前端·react.js