手写tomcat的一些思路

一、HttpRequest 封装思路

核心目标是解析 HTTP 请求报文,提取关键信息并封装为对象,简化后续处理。

  1. 定义核心成员变量:存储请求报文原始内容、请求方法(GET/POST)、请求 URL、请求模块、协议版本、请求参数(GET/POST 统一存储)、请求头参数等。
  2. 分步骤解析:先拆分请求报文为请求行、请求头、请求体三部分,再分别解析。
  3. 针对性处理:GET 请求参数从 URL 中提取,POST 请求参数从请求体中提取,请求头按 “Key: Value” 格式拆分存储。
  4. 提供便捷方法:通过 get 方法获取解析后的各类信息,无需重复解析逻辑。

二、HttpResponse 封装思路

核心目标是标准化 HTTP 响应格式,简化向客户端(浏览器)发送响应的操作。

  1. 定义核心成员变量:持有客户端 Socket 连接(用于获取输出流)、响应状态行(默认 HTTP/1.1 200 OK)、响应头(键值对存储)、响应体(字节数组形式)。
  2. 封装核心方法:提供 addHeader 方法灵活设置响应头,setBody 方法设置响应体,write 方法统一拼接响应格式(状态行→响应头→空行→响应体)并写入流。
  3. 细节优化:自动计算并补充 Content-Length 头部,统一处理换行符(\r\n)符合 HTTP 规范,支持动态传入媒体类型(适配不同资源)。
  4. 重载适配:支持直接传入字节数组(动态资源)或结合静态资源处理器(静态资源),简化调用。

三、静态资源处理器封装流程

核心目标是统一处理静态资源(HTML/CSS/JS/ 图片等)的读取、媒体类型匹配,简化静态资源响应。

  1. 定义核心属性:存储静态资源文件路径、文件字节数据、对应的媒体类型(Content-Type)。
  2. 初始化流程:通过构造方法传入文件路径,自动触发 “读取文件字节数据” 和 “匹配媒体类型” 两个核心操作。
  3. 关键功能实现:
    • 读取字节数据:通过 FileInputStream 读取文件,根据文件大小创建字节数组,存入文件字节数据。
    • 匹配媒体类型:根据文件后缀(.html/.css/.png 等)映射对应的媒体类型(如 text/html、image/png)。
  4. 对外提供接口:提供 getFileByte(获取文件字节)和 getMedia(获取媒体类型)方法,供 HttpResponse 调用。

四、静态资源与动态资源的判断逻辑

核心是区分 “直接返回文件” 和 “需执行业务逻辑生成响应” 两类请求,避免误判。

  1. 初始判断规则:通过请求模块(请求 URL 的核心路径)是否包含 “.” 来区分,包含则视为静态资源(如 /pages/index.html、/123.png)。
  2. 优化后判断规则(更严谨):
    • 先查询动态资源映射(配置文件或注解),若能匹配到对应的 Servlet,则为动态资源。
    • 若未匹配到,视为静态资源,交由 DefaultServlet 处理。
    • 若静态资源文件不存在,则返回 404 页面(动态资源不存在也返回 404)。

五、动态资源的一步步优化流程

核心目标是解耦业务逻辑与请求分发,提升扩展性和可维护性。

1. 初始阶段:switch-case 分发
  • 思路:在服务器主逻辑中,根据 HttpRequest 解析出的请求模块(如 /login、/enroll),通过 switch-case 分支匹配对应的业务逻辑。
  • 优点:实现简单,适合初期少量动态资源。
  • 缺点:耦合度极高,新增业务需修改主逻辑,违反开闭原则,维护成本随业务量增长而剧增。
2. 第一次优化:抽取 Servlet 基类(继承 + 多态)
  • 思路:将每个动态资源的业务逻辑抽取为独立 Servlet 类,继承 BaseServlet 抽象类。
  • 核心设计:BaseServlet 定义 doGet、doPost 抽象方法,以及 requestMethodHandler 方法(自动根据请求方法分发到 doGet/doPost)。
  • 优点:业务逻辑与主逻辑解耦,每个 Servlet 专注自身业务,符合单一职责原则。
  • 缺点:仍需通过 switch-case 匹配请求模块与 Servlet 实例,新增 Servlet 需修改分发逻辑。
3. 第二次优化:配置文件 + 反射
  • 思路:用配置文件(如 servlet.properties)存储 “请求模块 = Servlet 类名” 的映射关系,通过反射动态创建 Servlet 实例,替代 switch-case。
  • 核心步骤:
    1. 编写配置文件:如 /login=LoginServlet、/enroll=EnrollServlet。
    2. 编写工具类:加载配置文件到 HashMap,提供根据请求模块获取 Servlet 类名的方法。
    3. 反射创建实例:根据配置文件中的类名,通过 Class.forName 加载字节码,创建 Servlet 实例,调用 requestMethodHandler 方法。
  • 优点:新增动态资源只需修改配置文件,无需改动主逻辑,扩展性大幅提升。
4. 第三次优化:注解 + 包扫描(最终优化)
  • 思路:用自定义注解(如 @ServletMapping)标记 Servlet 对应的请求模块,通过包扫描工具自动识别带注解的 Servlet,替代配置文件。
  • 核心步骤:
    1. 定义自定义注解:@ServletMapping(作用于类,存储请求模块路径)。
    2. 编写扫描工具类:使用 Reflections 框架扫描指定包下带 @ServletMapping 注解的类。
    3. 自动映射存储:解析注解中的请求模块,通过反射创建 Servlet 实例,存入 HashMap。
    4. 分发请求:根据请求模块从 HashMap 中获取 Servlet 实例,调用业务方法。
  • 优点:无需配置文件,新增 Servlet 只需添加注解,配置零成本,扩展性和维护性达到最优。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值