手写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();}
}
关键步骤:
- 创建服务器套接字:监听 8080 端口。
- 接收客户端连接:通过
serverSocket.accept()
阻塞等待请求。 - 解析 HTTP 请求:
- 读取请求头的第一行(格式:
GET /path HTTP/1.1
)。 - 提取 HTTP 方法(如
GET
)和请求路径(如/login
)。
- 读取请求头的第一行(格式:
- 设置请求对象:将解析结果存入静态
request
对象。 - 分发请求:调用
dispatch()
方法查找并执行对应的 Servlet。
相关文章:
手写tomcat:基本功能实现(3)
TomcatRoute类 TomcatRoute类是Servlet容器,是Tomcat中最核心的部分,其本身是一个HashMap,其功能为:将路径和对象写入Servlet容器中。 package com.qcby.config;import com.qcby.Util.SearchClassUtil; import com.qcby.servlet…...
nt!MiRemovePageByColor函数分析之脱链和刷新颜色表
第0部分:背景 PFN_NUMBER FASTCALL MiRemoveZeroPage ( IN ULONG Color ) { ASSERT (Color < MmSecondaryColors); Page FreePagesByColor[Color].Flink; if (Page ! MM_EMPTY_LIST) { // // Remove the first entry on the zeroe…...
时间筛掉了不够坚定的东西
2025年5月17日,16~25℃,还好 待办: 《高等数学1》重修考试 《高等数学2》备课 《物理[2]》备课 《高等数学2》取消考试资格学生名单 《物理[2]》取消考试资格名单 职称申报材料 2024年税务申报 5月24日、25日监考报名 遇见:敲了一…...
3D个人简历网站 4.小岛
1.模型素材 在Sketchfab上下载狐狸岛模型,然后转换为素材资源asset,嫌麻烦直接在网盘链接下载素材, Fox’s islandshttps://sketchfab.com/3d-models/foxs-islands-163b68e09fcc47618450150be7785907https://gltf.pmnd.rs/ 素材夸克网盘&a…...
第十一课 蜗牛爬树
上次作业 同学们课后可以尝试找一下30以内,哪个整数有最多的因数呢? 这个整数有多少个因数呢? 最好使用程序来进行判断哦 int main() {int max_num 1; // 记录因数最多的数int max_count 1; // 记录最大因数个数for (int num 2; num <…...
字体样式集合
根据您提供的字体样式列表,以下是分类整理后的完整字体样式名称(不含数量统计): 基础样式 • Regular • Normal • Plain • Medium • Bold • Black • Light • Thin • Heavy • Ultra • Extra • Semi • Hai…...
Spring MVC 如何处理文件上传? 需要哪些配置和依赖?如何在 Controller 中接收上传的文件 (MultipartFile)?
Spring MVC 处理文件上传主要依赖于 MultipartResolver 接口及其实现。最常用的实现是 CommonsMultipartResolver(基于 Apache Commons FileUpload)和 StandardServletMultipartResolver(基于 Servlet 3.0 API)。 以下是如何配置…...
探索C++对象模型:(拷贝构造、运算符重载)成员函数的深度解读(中篇)
前引:在C的面向对象编程中,对象模型是理解语言行为的核心。无论是类的成员函数如何访问数据,还是资源管理如何自动化,其底层机制均围绕两个关键概念展开:拷贝复制、取地址重载成员函数。它们如同对象的“隐形守护者”&…...
[逆向工程]C++实现DLL注入:原理、实现与防御全解析(二十五)
[逆向工程]C实现DLL注入:原理、实现与防御全解析(二十五) 引言 DLL注入(DLL Injection)是Windows系统下实现进程间通信、功能扩展、监控调试的核心技术之一。本文将从原理分析、代码实现、实战调试到防御方案&#x…...
gcc/g++常用参数
1.介绍 gcc用于编译c语言,g用于编译c 源代码生成可执行文件过程,预处理-编译-汇编-链接。https://zhuanlan.zhihu.com/p/476697014 2.常用参数说明 2.1编译过程控制 参数作用-oOutput,指定输出名字-cCompile,编译源文件生成对…...
51单片机课设基于GM65模块的二维码加条形码识别
系统组成 主控单元:51单片机(如STC89C52)作为核心控制器,协调各模块工作。 扫描模块:GM65条码扫描头,支持二维码/条形码识别,通过串口(UART)与单片机通信。 显示模块&a…...
物联网赋能7×24H无人值守共享自习室系统设计与实践!
随着"全民学习"浪潮的兴起,共享自习室市场也欣欣向荣,今天就带大家了解下在物联网的加持下,无人共享自习室系统的设计与实际方法。 一、物联网系统整体架构 1.1 系统分层设计 层级技术组成核心功能用户端微信小程序/H5预约选座、…...
基于多头自注意力机制(MHSA)增强的YOLOv11主干网络—面向高精度目标检测的结构创新与性能优化
深度学习在计算机视觉领域的快速发展推动了目标检测算法的持续进步。作为实时检测框架的典型代表,YOLO系列凭借其高效性与准确性备受关注。本文提出一种基于多头自注意力机制(Multi-Head Self-Attention, MHSA)增强的YOLOv11主干网络结构,旨在提升模型在…...
使用Spring Boot与Spring Security构建安全的RESTful API
使用Spring Boot与Spring Security构建安全的RESTful API 引言 在现代Web应用开发中,安全性是不可忽视的重要环节。Spring Boot和Spring Security作为Java生态中的主流框架,为开发者提供了强大的工具来构建安全的RESTful API。本文将详细介绍如何结合S…...
小刚说C语言刷题—1230蝴蝶结
1.题目描述 请输出 n 行的蝴蝶结的形状,n 一定是一个奇数! 输入 一个整数 n ,代表图形的行数! 输出 n 行的图形。 样例 输入 9 输出 ***** **** *** ** * ** *** **** ***** 2.参考代码(C语言版)…...
利用SenseGlove触觉手套开发XR手术训练体验
VirtualiSurg和VR触觉 作为领先的培训平台,VirtualiSurg自2017年以来一直利用扩展现实 (XR) 和触觉技术,为全球医疗保健行业提供个性化、数据驱动的学习解决方案。该平台赋能医疗专业人员进行协作式学习和培训,提升他们的技能,使…...
CT重建笔记(五)—2D平行束投影公式
写的又回去了,因为我发现我理解不够透彻,反正想到啥写啥,尽量保证内容质量好简洁易懂 2D平行束投影公式 p ( s , θ ) ∫ ∫ f ( x , y ) δ ( x c o s θ y s i n θ − s ) d x d y p(s,\theta)\int \int f(x,y)\delta(x cos\theta ysi…...
【Java】应对高并发的思路
在Java中应对高并发场景需要结合多方面的技术手段和设计模式,从线程管理、数据结构、同步机制到异步处理、IO优化等,都需要合理设计和配置。以下是Java在高并发场景下的主要应对策略和最佳实践: 1. 线程管理 1.1 线程池(ThreadPo…...
从数据分析到数据可视化:揭开数据背后的故事
从数据分析到数据可视化:揭开数据背后的故事 大家好,今天咱们聊聊“从数据分析到数据可视化”的完整流程。说实话,数据分析和可视化这俩词听起来高大上,但咱们平时就是围绕这俩词打转——数据分析帮我们找故事,可视化则帮我们讲故事。没有它们,数据就是死的;有了它们,数…...
WPS JS宏实现去掉文档中的所有空行
WPS改造系列文章: 1.在WPS中通过JavaScript宏(JSA)调用本地DeepSeek API优化文档教程:在WPS中通过JavaScript宏(JSA)调用本地DeepSeek API优化文档教程_wps javascript-CSDN博客 2.在WPS中通过JavaScrip…...
【2025年软考中级】第一章1.6 安全性、可靠性、性能评价
文章目录 安全性、可靠性、性能评价计算机可靠性可靠性指标串并联系统可靠性并联系统可靠性N模元余系统 计算机系统性能评价信息安全加密技术对称(私钥)加密技术非对称加密技术(公钥)对称和非对称加密算法的区别数字信封原理数字签…...
MODBUS RTU通信协议详解与调试指南
一、MODBUS RTU简介 MODBUS RTU(Remote Terminal Unit)是一种基于串行通信(RS-485/RS-232)的工业标准协议,采用二进制数据格式,具有高效、可靠的特点,广泛应用于PLC、传感器、变频器等工业设备…...
【深度学习新浪潮】大模型时代,我们还需要学习传统机器学习么?
在大模型时代,AI 工程师仍需掌握传统机器学习知识,这不仅是技术互补的需求,更是应对复杂场景和职业发展的关键。以下从必要性和学习路径两方面展开分析: 一、传统机器学习在大模型时代的必要性 技术互补性 大模型(如GPT、BERT)擅长处理复杂语义和生成任务,但在数据量少…...
深入解析Spring Boot与Spring Security的集成实践
深入解析Spring Boot与Spring Security的集成实践 引言 在现代Web应用开发中,安全性是一个不可忽视的重要方面。Spring Security作为Spring生态中的安全框架,提供了强大的认证和授权功能。本文将结合Spring Boot,详细介绍如何集成Spring Se…...
嵌入式学习笔记 - STM32 使用一个外部触发同时启动两个定时器
一个定时器是同时可以设置成主模式跟从模式的, 下面例子中, 一 TM1首先被配置为主模式, 通过MMS001:使能 – 计数器使能信号CNT_EN被用于作为触发输出(TRGO)。见寄存器描述,此位默认为000,这时从模式状态…...
JWT令牌验证
一、JWT 验证方式详解 JWT(JSON Web Token)的验证核心是确保令牌未被篡改且符合业务规则,主要分为以下步骤: 1. 令牌解析与基础校验 收到客户端传递的 JWT 后,首先按 . 分割为三部分:Header、Payload、S…...
Go语言 GORM框架 使用指南
在 Go 语言社区中,数据库交互一直是开发者们关注的重点领域,不同开发者基于自身的需求和偏好,形成了两种主要的技术选型流派。一部分开发者钟情于像sqlx这类简洁的库,尽管其功能并非一应俱全,但它赋予开发者对 SQL 语句…...
c#车检车构客户管理系统软件车辆年审短信提醒软件
# CMS_VehicleInspection 车检车构客户管理系统软件车辆年审短信提醒软件 # 开发背景 软件是给泸州某公司开发的车检车构客户管理系统软件。用于在车检年审到期前一个月给客户发送车检短信提醒 # 功能描述 主要功能:车辆年审前一个月给客户发年审短信提醒…...
匿名函数与闭包(Anonymous Functions and Closures)-《Go语言实战指南》原创
Go 支持将函数当作值来使用,也允许定义匿名函数,并通过闭包实现对外部变量的捕获与持续访问。这一特性使函数式编程风格在 Go 中成为可能。 一、什么是匿名函数? 匿名函数是没有名字的函数,可以定义后立即调用,或赋值…...
兰亭妙微:用系统化思维重构智能座舱 UI 体验
兰亭妙微设计专注于以产品逻辑驱动的界面体验优化,服务领域覆盖AI交互、智能穿戴、IoT设备、智慧出行等多个技术密集型产业。我们倡导以“系统性设计”为方法论,在用户需求与技术边界之间找到最优解。 此次智能驾驶项目,我们为某车载平台提供…...
Flowbite 和 daisyUI 那个好用?
Flowbite 和 daisyUI 都是基于 Tailwind CSS 的组件库,它们各有特色,选哪个更好用,取决于你的项目需求和设计偏好。 简要结论 对比项daisyUIFlowbite上手难度简单,类名即组件略复杂(多用 HTML 结构)Vue 支…...
中间网络工程师知识点5
1.PKI证书主要用于确保主体公钥的合法性 2.VLAN帧的最小帧长是64字节,其中表示帧优先级的字是PRI 3.WIFI6是2.4GHZ和5GHZ频段的,理论吞吐量最高可达9.6Gbps,遵从协议802.11ax,支持完整版的MU-MIMO 4.在大型无线网络中,AP通过DHCP option43端口来获取AC的IP地址 5.项目…...
二、数据模型
二、数据模型 数据模型回顾 数据模型(Data Model) 是信息领域采用的模型将现实世界的各种事物以及事物之间的联系,表示为数据以及数据之间的联系是对现实世界数据特征的抽象和模拟用来描述数据、组织数据和操作数是数据库系统的核心和基础 …...
获取淘宝店铺所有商品信息接口数据指南
在电商运营和数据分析中,获取淘宝店铺的商品信息是常见的需求。淘宝开放平台提供了丰富的 API 接口,方便开发者获取商品的详细信息,包括商品列表、商品详情、销量等。本文将详细介绍如何从零开始获取淘宝店铺的所有商品信息,包括注…...
目标检测工作原理:从滑动窗口到Haar特征检测的完整实现
目标检测探索指南 🔍 目标检测就像是一位细心的侦探!我们需要在图像中寻找并定位特定的目标,就像侦探在现场搜寻线索一样。让我们一起来探索这个充满挑战的图像处理领域吧! 目录 1. 什么是目标检测?2. 滑动窗口检测3.…...
【LUT技术专题】针对降噪优化的通道感知轻量级LUT算法:DnLUT
DnLUT:Ultra-Efficient Color Image Denoising via Channel-Aware Lookup(2025 CVPR) 专题介绍一、研究背景二、DnLUT方法2.1 Pairwise Channel Mixer2.2 Rotation Non-overlapping Kernel(L型卷积) 三、实验结果四、总…...
支持同步观看的媒体服务器GhostHub
简介 什么是 GhostHub ? GhostHub 是一个基于滑动界面的媒体服务器,旨在实现实时同步、聊天和隧道分享。它允许用户快速共享和浏览媒体内容,无需复杂的配置或帐户。 主要特点 零配置: 即开即用,无需安装或创建帐户。滑动浏览: 提…...
告别 pip:使用 uv 加速你的 Python 包管理
使用 uv:更快的 Python 包管理工具 随着 Python 生态的演进,包管理工具也在不断升级迭代。uv 是 Astral(同样维护 ruff 的团队)推出的下一代 Python 包与项目管理器,主打 单一可执行文件、极致性能,可在多数场景下取代 pip、pip-tools、pipx 与 virtualenv 等传统工具,…...
使用glsl 来做视频矫正
描述、优点 使用glsl来代替opencv的undistort 和 鱼眼矫正,并且最后使用opencv的LUT给glsl 来使用,来达到加速的目的,并且做到和opencv 一模一样的效果,达到实时视频的加速矫正。 优点: 没有cuda,也可以做到实时视频矫正,包含各类板子和amd的cpu,intel核显 矫正的基本作…...
【VSCode】快捷键合集(持续更新~)
一、基础编辑操作 注释/取消注释 Ctrl /:快速注释或取消注释当前行或选中行。ctrlshift/:块注释 代码格式化 • Shift Alt F:格式化整个文档,统一代码风格。 行操作 • Alt ↑/↓:向上/向下移动当前行。 • Shi…...
MATLAB学习笔记(七):MATLAB建模城市的雨季防洪排污的问题
使用 MATLAB 对城市雨季防洪排污问题进行建模与仿真,需要结合数学模型、工程经验和 MATLAB 的数值计算、数据可视化及优化工具。以下是详细的步骤指南,包含实际案例和代码示例: 一、问题分析与建模框架 1. 问题拆解 • 核心目标: …...
由浮点数x的位级表示求其整型值
由浮点数x的位级表示,得到浮点数的十进制表示,在超过32位整型数的表示范围时,返回0X80000000;在32位整型数的表示范围内时,返回强制转化为整型的值。舍入时采用向0舍入。 程序代码 typedef unsigned long int float_…...
【Qt】Qt常见控件的相关知识点
1.close退出槽函数 2.设置快捷键,QMenu 。 适用&字母就能设置快捷键,运行qt程序,最后就可以按Alt对应的字母进行快捷操作。 3.QMenuBar内存泄露问题 如果ui已经自动生成了menubar,我们再次生成一个新的菜单栏,而…...
数据结构*优先级队列(堆)
什么是优先级队列(堆) 优先级队列一般通过堆(Heap)这种数据结构来实现,堆是一种特殊的完全二叉树,其每个节点都满足堆的性质。如下图所示就是一个堆: 堆的存储方式 由于堆是一棵完全二叉树,所以也满足二…...
Windows本地化部署Dify完整指南
Windows本地化部署Dify完整指南 作者:朱元禄 版权声明:本文为朱元禄原创文章,转载请注明出处及作者信息 关键词:Dify部署,Windows安装Dify,Dify本地化,Dify教程,Dify配置,朱元禄 一、Docker Desktop安装与配置 1.1 下载Docker De…...
全局异常处理:如何优雅地统一管理业务异常
在软件开发中,异常处理是保证系统健壮性的重要环节。一个良好的异常处理机制不仅能提高代码的可维护性,还能为使用者提供清晰的错误反馈。本文将介绍如何通过全局异常处理和业务异常统一处理来编写更加优雅的代码。 一、传统异常处理的痛点 1.1 典型问…...
AI517 AI本地部署 docker微调(失败)
本地部署AI 计划使用OLLAMA进行本地部署 修改DNS 访问github 刷新缓存 配置环境变量 OLLAMA安装成功 部署成功 计划使用docker进行微调 下载安装docker 虚拟化已开启 开启上面这些 准备下载ubuntu docker ragflow dify 用git去泡...
C++(初阶)(十八)——AVL树
AVL树 AVL树概念实现AVL树的结点插入插入方法 平衡因子更新更新停止条件旋转右单旋左单旋左右双旋右左双旋 遍历AVL平衡检测 完整代码 概念 1,AVL树是最先发明的⾃平衡⼆叉查找树,AVL树是⼀颗⾼度平衡搜索⼆叉树, 通过控制高度差去控制平衡。…...
2022河南CCPC(前四题)
签到题目 #include <bits/stdc.h> using namespace std; #define int long long #define PII pair<int,int> #define fi first #define se second #define endl \n #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);void solve() {int n;cin>>…...
【滑动窗口】LeetCode 1658题解 | 将 x 减到 0 的最小操作数
将 x 减到 0 的最小操作数 一、题目链接二、题目三、题目解析四、算法原理五、编写代码六、时空复杂度 一、题目链接 将 x 减到 0 的最小操作数 二、题目 三、题目解析 以示例1为例: 四、算法原理 像"题目解析"中正面删除并修改数组元素的操作太困难&…...