点一下关注吧!!!非常感谢!!持续更新!!!

🚀 AI篇持续更新中!(长期更新)

目前2025年06月13日更新到:
AI炼丹日志-28 - Audiblez 将你的电子书epub转换为音频mp3 做有声书,持续打造实用AI工具指南!📐🤖

💻 Java篇正式开启!(300篇)

目前2025年06月11日更新到:
Java-44 深入浅出 Nginx - 底层进程机制 Master Worker 机制原理 常用指令
MyBatis 已完结,Spring 已完结,深入浅出助你打牢基础!

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
目前2025年06月13日更新到:
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

请添加图片描述

MiniCat

基本介绍

我们要手写实现一个 Mini 版的 Tomcat,我们要实现的是,作为一个服务器软件,可以通过我们的浏览器客户端发送HTTP请求,Minicat处理之后,处理结果可以返回给浏览器的客户端。
● 提供服务,接受请求(Socket通信)
● 请求信息封装成 Request 对象(Response对象)
● 客户端请求资源,资源分为静态资源(HTML)和动态资源(Servlet)
● 资源返回客户端浏览器

HttpProtocoUtil 协议类

public class HttpProtocoUtil {public static String getHttpHeader200(long contentLength) {return "HTTP/1.1 200 OK \n" +"Content-Type: text/html \n" +"Content-Length: " + contentLength + " \n" +"\r\n";}public static String getHttpHeader404() {String str404 = "<h1>404 not found</h1>";return "HTTP/1.1 404 NOT Found \n" +"Content-Type: text/html \n" +"Content-Length: " + str404.getBytes().length + " \n" +"\r\n" + str404;}
}

HttpProtocoUtil,它封装了两个方法,用于手动构造 HTTP 响应报文字符串,分别用于:

  • 返回 HTTP 200 成功响应的报文头;
  • 返回 HTTP 404 未找到的完整响应报文(包含 header + body)。

关键点分析:

  • str404: 定义了一个 HTML 格式的正文

    404 not found

  • str404.getBytes().length: 计算正文的字节数,填入 Content-Length 字段中
  • 最后 + str404: 将正文内容添加在头部之后

HttpServlet 基础类

public abstract class HttpServlet implements Servlet {public abstract void doGet(Request request,Response response);public abstract void doPost(Request request,Response response);@Overridepublic void service(Request request, Response response) throws Exception {if("GET".equalsIgnoreCase(request.getMethod())) {doGet(request,response);}else{doPost(request,response);}}
}

简化版的 HttpServlet 类,是你手写 Web 容器(例如 MiniCat)中模仿 Java EE javax.servlet.http.HttpServlet 的核心组件。

  • abstract class: 抽象类,不能直接被实例化,必须由子类实现其抽象方法。
  • implements Servlet: 表示这个类实现了一个自定义的 Servlet 接口(你可能已经自己定义了 Servlet 接口),这与 Java Web 中的标准接口 javax.servlet.Servlet 类似。

在抽象方法中:

  • 声明了两个抽象方法,分别用于处理 GET 请求 和 POST 请求。

  • 子类必须实现它们,否则编译报错。

Request request: 封装了 HTTP 请求的信息(如 URI、参数、方法类型等)。

  • Response response: 封装了 HTTP 响应的信息(如设置状态码、响应内容等)。

这两个类也应该是你自己定义的简化版 Request 和 Response 类,用于模拟真实的 Servlet API 行为。

而在service(Request, Response)中:

  • 实现了 Servlet 接口中的 service() 方法,作为请求处理的统一入口。

  • 根据 request.getMethod() 返回的 HTTP 方法(如 “GET” 或 “POST”),分发给 doGet() 或 doPost() 方法。

  • equalsIgnoreCase: 忽略大小写比较,兼容 “get”, “GET” 等写法。

  • request.getMethod(): 获取请求方法字符串,应该是你自定义 Request 类中的一个方法。

  • throws Exception: 表明此方法可能抛出异常,让调用方去处理,便于灵活控制异常响应。

假设我们有一个具体的实现类:

public class HelloServlet extends HttpServlet {@Overridepublic void doGet(Request req, Response resp) {resp.write("Hello, GET!");}@Overridepublic void doPost(Request req, Response resp) {resp.write("Hello, POST!");}
}

当用户访问你的 Web 服务 /hello 时:

  • 如果是 GET 请求,会调用 doGet(),返回 “Hello, GET!”。
  • 如果是 POST 请求,会调用 doPost(),返回 “Hello, POST!”。

Request 请求处理类

public class Request {private String method;private String url;private InputStream inputStream;public Request() {}public Request(InputStream inputStream) throws IOException {this.inputStream = inputStream;int count = 0;while (count == 0) {count = inputStream.available();}byte[] bytes = new byte[count];inputStream.read(bytes);String inputStr = new String(bytes);// 请求头String firstLineStr = inputStr.split("\\n")[0];String[] strings = firstLineStr.split(" ");this.method = strings[0];this.url = strings[1];System.out.println("Request method: " + method + ", url: " + url);}public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public InputStream getInputStream() {return inputStream;}public void setInputStream(InputStream inputStream) {this.inputStream = inputStream;}
}

在类属性中:

  • method:HTTP 请求方法(如 GET, POST)
  • url:请求的资源路径(如 /index.html)
  • inputStream:从客户端 socket 获取的原始请求数据流

在 inputStream.available() 循环读取,目的是等到客户端数据准备好再读取。

while (count == 0) {count = inputStream.available();
}

RequestProcessor 响应类

public class RequestProcessor extends Thread {private Socket socket;private Map<String, HttpServlet> servletMap;public RequestProcessor(Socket socket, Map<String, HttpServlet> servletMap) {this.socket = socket;this.servletMap = servletMap;}@Overridepublic void run() {try {InputStream inputStream = socket.getInputStream();Request request = new Request(inputStream);Response response = new Response(socket.getOutputStream());// 静态资源if (servletMap.get(request.getUrl()) == null) {response.outputHtml(request.getUrl());} else {HttpServlet servlet = servletMap.get(request.getUrl());servlet.service(request, response);}socket.close();} catch (Exception e) {e.printStackTrace();}}
}

RequestProcessor 这是一个继承了 Thread 的类,意味着每次请求会以独立线程的方式进行处理。它负责解析 HTTP 请求、查找对应的 Servlet 处理器,或返回静态资源。在简易 Web Server 中,每当 ServerSocket.accept() 接收到一个连接,就会创建这个类的一个实例,并调用 start() 进入 run() 方法处理。

此外,在RequestProcessor(Socket socket, Map<String, HttpServlet> servletMap)构造函数中,将 socket 和 servlet 映射传入,以便在 run() 方法中使用。这也是多线程处理请求的基础结构:每个线程独立处理一个连接,不共享 socket。

在核心处理逻辑中 run():从 socket 获取输入流、输出流,构造出 Request 和 Response 对象。Request 负责解析 HTTP 请求头;Response 封装输出功能(例如写 HTML 响应)。

另外,在请求分发逻辑中,“servletMap.get(request.getUrl())”:

  • 静态资源路径(如 /index.html):不在 servletMap 中,调用 response.outputHtml(),你很可能实现了这个方法来读取本地文件并写入 socket。
  • 动态 Servlet 路径(如 /hello):在 servletMap 中,调用 servlet.service(),执行对应的业务逻辑(最终调用 doGet() 或 doPost())。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84799.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84799.shtml
英文地址,请注明出处:http://en.pswp.cn/web/84799.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在VB.net中,文本插入的几个自定义函数

一、如果你是高手&#xff0c;一定“识货”&#xff0c;分享给你 二、可应用于文本插入的几种方式&#xff1a;6种 三、需要用到以下的几个函数&#xff1a; 上代码&#xff1a; Module TextModule <summary> 在指定位置插入文本 </summary> <p…

QC -io 服务器排查报错方式/报错: Failed to convert string to integer of varId variable!“

进断点控制台有报错之后&#xff0c;复制报错信息到 头部菜单栏 1.编辑 -> 2.Find/Replace ->3.Advanced Find ->4. Project“xxxxx” 能找到问题点 再分析定位 在排查报错时候&#xff0c;进入了这个报错&#xff0c;msgInfo "MyTcpRedis: Failed to conver…

c++中auto与decltype使用

在 C11及后续版本中&#xff0c;关键字auto和decltype都是用于类型推导的&#xff0c;但它们的使用场景和行为有所不同。 1. auto 关键字 作用 auto 用于自动推导变量的类型&#xff0c;由编译器根据初始化表达式来确定。 常见用法 // 基本用法 auto x 42; // int…

LabVIEW机器视觉零件检测

基于LabVIEW 图形化编程平台与机器视觉技术&#xff0c;构建集图像采集、处理、尺寸计算与合格性分析于一体的自动化检测方案。通过模块化硬件架构与自适应算法设计&#xff0c;实现对机械零件多维度尺寸的非接触式高精度测量&#xff0c;相比人工检测效率提升 12 倍&#xff0…

大数据治理域——实时数据开发

摘要 本文深入探讨了大数据治理域中的实时数据开发&#xff0c;重点介绍了流式数据处理的核心价值、特点、技术挑战、典型能力和应用场景。同时&#xff0c;详细阐述了流式技术架构&#xff0c;包括数据采集、处理、存储和服务等环节&#xff0c;并针对大促场景提出了相应的技…

Halcon/C# 图像窗口、读取图片及仿射变换

一、Halcon 清理窗口 清除图像窗口的显示。 dev_clear_window() 二、Halcon 读取图片 (一) 读取一张图片 read_image (Image, printer_chip/printer_chip_01)Image&#xff1a;&#xff08;输出参数&#xff09;读取到的图片变量名 第二个参数&#xff1a;图片路径&#xf…

Nginx 反向代理服务和安装docker-compose

Nginx 反向代理服务和安装docker-compose Nginx Proxy Manager 他是一个可视化的nginx的反向代理神器&#xff0c;动动手指轻松的配置Nginx&#xff0c;我们可以通过一些网页&#xff0c;即可完成网站的代理配置&#xff0c;无需在动手安装Nginx&#xff1b; dockoer-compose部…

FPGA基础 -- Verilog 锁存器简介

由浅入深地讲解 Verilog 中的锁存器&#xff08;Latch&#xff09;**&#xff0c;包括&#xff1a; 什么是锁存器&#xff08;定义与作用&#xff09;锁存器的分类&#xff08;透明锁存器 vs 边沿触发器&#xff09;Verilog 中锁存器的建模方式锁存器与触发器的区别锁存器的时…

Eclipse Memory Analyzer (MAT) 相关配置调整

一、JDK版本过低提示 已安装高于 jdk 17 的版本依旧提示 jdk 版本过低&#xff0c;打开MAT的安装目录&#xff0c;在配置文件 MemoryAnalyzer.ini 中添加配置指向JDK即可。新增两行配置&#xff1a; -vm D:/jdk_21.0.7/bin/javaw.exe //jdk安装路径 bin 目录下的javaw.exe二…

机器学习常用评估指标

机器学习常用评估指标 机器学习的评价指标有精度、精确率、召回率、P-R曲线、F1 值、TPR、FPR、ROC等指标&#xff0c;还有在生物领域常用的敏感性、特异性等指标。 基础 在分类任务中&#xff0c;各指标的计算基础都来自于对正负样本的分类结果&#xff0c;用混淆矩阵表示&…

视频相似度检测算法(带课设报告)

摘 要 本文提出了一种基于关键帧特征提取的视频相似度检测方法&#xff0c;通过融合自适应采样与特征降维技术实现高效准确的视频内容比对。系统采用三阶段处理流程&#xff1a;首先对输入视频进行自适应关键帧采样&#xff0c;通过均匀间隔算法提取固定数量&#xff08;默…

微服务江湖的爱恨情仇:Spring Cloud 与 Kubernetes 的双雄演义

引言&#xff1a;双雄并立&#xff0c;一个时代的序幕 微服务革命&#xff0c;如同一场燎原之火&#xff0c;将庞大、笨重的单体应用烧成灰烬&#xff0c;宣告了一个敏捷、独立、快速迭代的新纪元。然而&#xff0c;这场革命在摧毁旧世界的同时&#xff0c;也催生了一片混沌的新…

深度拆解RAGFlow分片引擎之切片实现

上一篇深度拆解RAGFlow分片引擎&#xff01;3大阶段视觉增强&#xff0c;全网最硬核架构解析 讲了切片的整体流程&#xff0c;今天我们来拆下切片的实现。 我们在设置的时候&#xff0c;可以选择切片方法。这个参数是parser_id 在创建知识库的时候&#xff0c;选择对应的切片方…

CSS平滑滚动效果实现方法

一、纯CSS实现方案 使用 scroll-behavior 属性 属性值 auto (默认值)&#xff1a;滚动框立即滚动smooth&#xff1a;滚动框以平滑的方式滚动 /* 全局平滑滚动 */ html {scroll-behavior: smooth; }/* 特定容器平滑滚动 */ .scroll-container {scroll-behavior: smooth;over…

李沐动手深度学习(pycharm中运行笔记)——12.权重衰退

12.权重衰退&#xff08;与课程对应&#xff09; 目录 一、权重衰退 1、使用均方范数作为硬性限制 2、使用均方范数作为柔性限制&#xff08;通常这么做&#xff09; 3、演示对最优解的影响 4、参数更新法则 5、总结 二、代码实现从零实现 三、代码实现简介实现 一、权重…

React Native【实战范例】同步跟随滚动

最终效果 实现原理 主动滚动区触发滚动事件&#xff0c;原生监听滚动值的变化&#xff0c;并用动画的方式实时同步到跟随滚动区 技术要点 使用 Animated.ScrollView 使用动画变量 const scrollY useRef(new Animated.Value(0)).current;主动滚动触发 onScroll&#xff0c;用 …

如何仅用AI开发完整的小程序<3>—创建小程序基础框架

1、启动小程序开发者工具-选择小程序&#xff0c;点击 2、创建一个项目工程 项目名称&#xff1a;自己填默认的也行&#xff0c;最好不要中文&#xff0c;拼音也行 目录&#xff1a;选择你的项目创建路径 AppID&#xff1a;可以先点测试号&#xff0c;后面再替换自己的AppID就…

SQL等价改写优化

or 与 union all的优化 在SQL开发中&#xff0c;我们经常会遇到这样的情况&#xff1a;需要组合多个相似但略有不同的查询结果。大多数开发者本能地使用UNION/UNION ALL来解决&#xff0c;这种方式直观易懂&#xff0c;但在特定场景下却隐藏着巨大的性能浪费。 本案例将从执行…

【已解决】 数据库INSERT操作时,Column count doesn’t match value count at row 1

【已解决】数据库INSERT操作时&#xff0c;ColumnColumn count doesn’t match value count at row 1 在开发过程中&#xff0c;我们经常会遇到数据库操作错误&#xff0c;其中之一就是 MySQL 中的 “Column count doesn’t match value count at row1” 错误。这个错误通常发…

管件接头的无序抓取

文章目录 1&#xff0c;目的2&#xff0c;过程3&#xff0c;易混易错点4&#xff0c;代码详解4.1&#xff0c;初始化窗口4.2&#xff0c;创建多视角立体视觉模型。4.3&#xff0c;创建表面匹配模型4.4&#xff0c;多视角立体视觉重建管件堆表面模型4.5&#xff0c;管道接头查找…