当前位置: 首页 > article >正文

手写tomcat:基本功能实现(3)

 TomcatRoute类

TomcatRoute类是Servlet容器,是Tomcat中最核心的部分,其本身是一个HashMap,其功能为:将路径和对象写入Servlet容器中。

package com.qcby.config;import com.qcby.Util.SearchClassUtil;
import com.qcby.servlet.Httpservlet;
import com.qcby.zj.YbyServlet;import java.util.HashMap;
import java.util.List;import java.util.List;
import java.util.Map;public class TomcatRoute {public static HashMap<String, Httpservlet> Route = new HashMap<>();static {List<String> classesPath = SearchClassUtil.searchClass();for (String path : classesPath) {try {//加载类Class clazz = Class.forName(path);//获取注解YbyServlet webServlet = (YbyServlet) clazz.getDeclaredAnnotation(YbyServlet.class);
//                对象Object servlet = clazz.getDeclaredConstructor().newInstance();Route.put(webServlet.url(), (Httpservlet) servlet);
//                Httpservlet servlet = (Httpservlet) clazz.newInstance();
//                servletMap.put(webServlet.url(),servlet);System.out.println(Route);} catch (Exception e) {e.printStackTrace();}}}}

 静态代码块 

1. 确保初始化时机

静态代码块在类加载时自动执行,且仅执行一次。这确保了路由表在程序启动时就被初始化,后续无需手动调用初始化方法。

对比其他初始化方式
  • 构造函数:每次创建对象时都会执行,而路由表只需初始化一次。
  • 普通静态方法:需要手动调用,可能被遗忘或重复调用。
  • 静态代码块:自动触发,保证全局唯一性。

2. 全局唯一性

静态代码块属于类,而非某个实例。无论创建多少个TomcatRoute对象,路由表只会初始化一次。

功能

  • 自动扫描:通过 SearchClassUtil.searchClass() 扫描项目中的所有类。
  • 注解识别:使用 @YbyServlet 注解标记需要注册的 Servlet。
  • 路由映射:将注解中的 url() 值作为路径,对应的 Servlet 实例作为值,存入静态的 Route 映射表。
  • 类加载时初始化:利用静态代码块在类加载时执行初始化逻辑,确保路由表在程序启动时就已准备好。

public static HashMap<String, Httpservlet> Route = new HashMap<>();

1. 多态性的应用

Httpservlet是所有具体 Servlet 的抽象父类(或接口),通过父类类型引用子类实例,可以实现统一调用

2. 解耦路由逻辑与具体实现

路由系统只需关注请求路径与处理逻辑的映射关系,而无需关心具体 Servlet 的实现细节。

3. 统一接口定义

Httpservlet通常定义了处理请求的标准方法(如service()doGet()doPost()),所有子类必须实现这些方法。

4. 符合 Servlet 规范

在标准 Java Web 开发中,所有 Servlet 都必须实现javax.servlet.Servlet接口(或继承HttpServlet)。这种设计模仿了标准 Servlet 容器的工作原理。

MyTomcat

package com.qcby;
//tomcat主启动类
import com.qcby.config.TomcatRoute;
import com.qcby.servlet.Httpservlet;
import com.qcby.Request.HttpServletRequest;
import com.qcby.Response.HttpServletResponse;import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;public class Mytomcat {static HashMap<String,Httpservlet> routes= TomcatRoute.Route;static  HttpServletRequest request=new HttpServletRequest();static  HttpServletResponse response=new HttpServletResponse();public  static void dispatch(){Httpservlet servlet=routes.get(request.getPath());if(servlet!=null){servlet.service(request,response);}}public static void main(String[] args) {try {System.out.append("服务器启动......");
//				1.定义ServerSocket对象进行服务器的端口注册ServerSocket serverSocket = new ServerSocket(8080);while (true) {
//				2.监听客户端的socket链接程序Socket socket = serverSocket.accept();//阻塞监听
//				3.从socket对象当中获得一个字节流对象InputStream iStream = socket.getInputStream();//				打印输出int len = 0;int ReviceLen = 0;
//			计算机网络数据是以8bit为一个单元进行发送,我们接收到发送方发生的byte数据
//				将其转化为utf-8格式输出byte[] recvBuf = new byte[1024];while ((ReviceLen = iStream.read(recvBuf)) != -1) {String count=new String(recvBuf,0,ReviceLen,"UTF-8");String method=count.split(" ")[0];String url=count.split(" ")[1];request.setMethod(method);request.setPath(url);}dispatch();}} catch(Exception e){// TODO: handle exception}}}

1. 整体架构

这个简易服务器包含三个核心组件:

  • Mytomcat:主服务器类,负责接收请求和分发。
  • TomcatRoute:路由配置类,通过静态代码块扫描并注册所有 Servlet。
  • Httpservlet:抽象 Servlet 基类,定义请求处理接口。

2. 核心成员变量 

static HashMap<String,Httpservlet> routes = TomcatRoute.Route;
static HttpServletRequest request = new HttpServletRequest();
static HttpServletResponse response = new HttpServletResponse();
  • routes:从 TomcatRoute 获取的路由表,存储 URL → Servlet 的映射关系。
  • request 和 response:静态全局对象,用于存储当前请求和响应信息。

 3. 请求分发逻辑

public static void dispatch() {Httpservlet servlet = routes.get(request.getPath());if (servlet != null) {servlet.service(request, response);}
}
  • 根据 request.getPath() 从路由表中查找对应的 Servlet。
  • 调用 Servlet 的 service() 方法处理请求(多态调用)。

4. 主服务器逻辑

public static void main(String[] args) {try {System.out.println("服务器启动......");ServerSocket serverSocket = new ServerSocket(8080);while (true) {// 1. 监听客户端连接(阻塞)Socket socket = serverSocket.accept();InputStream iStream = socket.getInputStream();// 2. 解析HTTP请求byte[] recvBuf = new byte[1024];int ReviceLen = iStream.read(recvBuf);String count = new String(recvBuf, 0, ReviceLen, "UTF-8");String method = count.split(" ")[0];String url = count.split(" ")[1];// 3. 设置请求信息request.setMethod(method);request.setPath(url);// 4. 分发请求dispatch();}} catch (Exception e) {e.printStackTrace();}
}

关键步骤

  1. 创建服务器套接字:监听 8080 端口。
  2. 接收客户端连接:通过 serverSocket.accept() 阻塞等待请求。
  3. 解析 HTTP 请求
    • 读取请求头的第一行(格式:GET /path HTTP/1.1)。
    • 提取 HTTP 方法(如 GET)和请求路径(如 /login)。
  4. 设置请求对象:将解析结果存入静态 request 对象。
  5. 分发请求:调用 dispatch() 方法查找并执行对应的 Servlet。
http://www.lryc.cn/news/2380053.html

相关文章:

  • Spring Cloud Seata 快速入门及生产实战指南
  • 电商平台自动化
  • Java微服务架构实战:Spring Boot与Spring Cloud的完美结合
  • 王树森推荐系统公开课 召回11:地理位置召回、作者召回、缓存召回
  • 无刷直流水泵构成及工作原理详解--【其利天下技术】
  • less中使用 @supports
  • 大数据:新能源汽车宇宙的未来曲率引擎
  • 【Java ee】关于抓包软件Fiddler Classic的安装与使用
  • 第五部分:第五节 - Express 路由与中间件进阶:厨房的分工与异常处理
  • 在 CentOS 7.9 上部署 node_exporter 并接入 Prometheus + Grafana 实现主机监控
  • C++--内存管理
  • Java实现PDF加水印功能:技术解析与实践指南
  • Django + Celery 打造企业级大模型异步任务管理平台 —— 从需求到完整实践(含全模板源码)
  • TC3xx学习笔记-UCB BMHD使用详解(二)
  • 用Python实现数据库数据自动化导出PDF报告:从MySQL到个性化文档的全流程实践
  • 实战设计模式之状态模式
  • 人工智能、机器学习与深度学习:概念解析与内在联系
  • 什么是着色器 Shader
  • Redis的主从架构
  • 博客系统功能测试
  • 【深度学习新浪潮】什么是多模态大模型?
  • 机器学习前言2
  • 【成品设计】基于Arduino的自动化农业灌溉系统
  • 前端页面 JavaScript数据交互
  • esp32课设记录(三)mqtt通信记录 附mqtt介绍
  • string类(详解)
  • MATLAB | R2025a 更新了哪些有趣的东西?
  • 前缀和——和为K的子数组
  • React 第四十二节 Router 中useLoaderData的用途详解
  • 千问大模型部署