手写tomcat(2):Servlet原理和自定义tomcat

作为 Java 后端开发,我们每天都在用 Tomcat,但你真的懂它和 Servlet 的底层逻辑吗?今天就从Servlet 的继承关系Tomcat 的请求流程 ,讲到如何手写一个简易 Tomcat,彻底搞懂 Web 容器的核心原理。

一、Servlet原理

Servlet 是 Java EE 定义的Web 组件接口,负责处理 HTTP 请求、生成响应。但直接用 Servlet 接口太麻烦,所以 Java EE 提供了 "接口 - 抽象类 - 实现类" 的简化体系:

1.1Servlet 的继承关系(核心分层)

Servlet 接口:定义了 Servlet 的生命周期方法(5 个核心方法):

java 复制代码
// Servlet接口的核心方法
init()          // 初始化:创建Servlet对象
getServletConfig() // 获取配置信息
service()       // 处理请求(核心)
getServletInfo() // 获取运行信息
destroy()       // 销毁对象

GenericServlet 抽象类 :帮我们实现了 Servlet 接口中除service()外的所有方法,减少重复代码。

HttpServlet 抽象类 :在 GenericServlet 基础上,把service()方法拆分成了 HTTP 请求对应的方法(doGet()doPost()等),适配 HTTP 协议。

自定义 Servlet 类 :我们实际开发时,只需要继承 HttpServlet,重写doGet()/doPost()即可。

二、Tomcat 是怎么工作的?请求从发起到响应的全流程

当你在浏览器输入http://ip:8080/xxx/my,Tomcat 到底做了哪些事?

2.1.Tomcat 请求处理流程(核心步骤)

1.网络通信层:Socket+ BIO/NIO

(1)Tomcat 通过网卡监听端口(比如 8080),用 Socket 建立客户端与服务器的连接;

(2)早期 Tomcat用BIO(阻塞 IO):一个请求占一个线程,效率低;后来升级为 NIO/AIO(非阻塞 IO)优化性能。

2.请求解析层:拆 HTTP 报文

(1)通过InputStream读取请求数据,解析出请求地址、请求类型(GET/POST)、Cookie等信息。

3.Servlet 容器:匹配对应的 Servlet

(1)Tomcat 内部维护了一个HashMap 容器 (Servlet 容器),key是 Servlet 的访问路径(比如/my),value是对应的 Servlet 对象;

(2)用解析出的请求地址作为key,找到对应的 Servlet 对象(比如MyServlet)。

4.调用 Servlet 处理请求

(1)根据请求类型(GET/POST),调用 Servlet 的doGet()/doPost()方法,处理业务逻辑并生成响应。

5.返回响应:通过 OutputStream 写回数据

(1)把响应结果通过OutputStream写回客户端,完成请求流程。

三、动手写一个简易 Tomcat:核心逻辑拆解

明白了 Tomcat 的原理,我们可以自己实现一个极简版 Web 容器,核心只需要 4 步:

步骤 1:启动时初始化 Servlet 容器

Tomcat 启动时,会扫描项目中的 Servlet 并初始化容器:

  1. 扫描 Servlet 类:遍历项目文件夹,获取所有 Servlet 类的全路径名;
  2. 解析 @WebServlet 注解 :读取注解中的访问路径(比如@WebServlet("/my"));
  3. 生成 Servlet 容器:用 HashMap 存储 "访问路径 → Servlet 对象" 的映射(通过反射创建 Servlet 对象)。

步骤 2:监听端口,接收请求

用 Socket 监听指定端口(比如 8080),等待客户端连接:

java 复制代码
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept(); // 阻塞等待请求

步骤 3:解析请求,封装 Request 对象

读取 Socket 的输入流,解析 HTTP 请求的路径、请求类型、参数 等信息,封装成自定义的HttpServletRequest对象。

步骤 4:匹配 Servlet / 静态资源,处理请求

  1. 匹配 Servlet :用请求路径从 HashMap 容器中找对应的 Servlet 对象,调用对应的doGet()/doPost()方法;
  2. 处理静态资源:如果请求的是 HTML/CSS/JS 等静态资源,直接读取文件并返回;
  3. 404 处理:既不是 Servlet 也不是静态资源时,返回 404 错误。

步骤 5:封装 Response,返回结果

把处理后的响应数据封装成HttpServletResponse对象,通过 Socket 的输出流写回客户端。

四、总结:Web 容器的核心本质

不管是 Tomcat 还是我们手写的简易容器,核心逻辑都是:

网络通信:用 Socket 实现客户端 - 服务器的连接;

请求解析:拆分 HTTP 报文,提取关键信息;

Servlet 管理:用容器(HashMap)管理 Servlet,实现 "路径→组件" 的映射;

请求分发:根据请求信息调用对应的组件(Servlet / 静态资源),生成响应。

相关推荐
Seven9744 分钟前
数据结构——树
java
李贺梖梖1 小时前
day05 数组
java
古城小栈1 小时前
Jenkins 自动构建 搞起来
java·servlet·jenkins
又是忙碌的一天1 小时前
servlet的体系原理+tomcat原理
java·servlet·tomcat
一叶飘零_sweeeet1 小时前
Java 17 异步多线程视频上传实战
java·文件上传
百锦再1 小时前
.NET到Java的终极迁移指南:最快转型路线图
android·java·开发语言·python·rust·go·.net
stella·1 小时前
RabbitMQ是什么?如何使用
java·分布式·中间件·消息队列·rabbitmq·削峰填谷
在坚持一下我可没意见1 小时前
Spring Boot 实战(一):拦截器 + 统一数据返回 + 统一异常处理,一站式搞定接口通用逻辑
java·服务器·spring boot·后端·spring·java-ee·tomcat
廋到被风吹走1 小时前
【JDK版本】JDK1.8相比JDK1.7 语言特性之函数式编程
java·开发语言·python