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

用BIO实现tomcat

一、前言

本课程的难度较高,需要将Servlet原理和IO课程全部学完。

二、当前项目使用方式

(1).自定义servlet

自定义servlet需要实现@WebServlet并且实现name和urlMapping
在这里插入图片描述
重启进行访问
http://localhost:8090/myServlet
在这里插入图片描述

(2).自定义html

在这里插入图片描述
重启进行访问
http://localhost:8090/index.html
在这里插入图片描述

(3).关于servlet位置

在这里插入图片描述
在SearchClassUtil类当中可以设置servlet包的位置

三、关于web须知

我们本次设计的tomcat能够将用户请求的资源进行返回

资源分类
1.静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源。静态资源可以直接被浏览器解析。*例如:html/css/jpg/js..
2.动态资源:每个用户访问相同的资源后,得到的结果可能不一样,称为动态资源。动态资源被访问后需要先转化为静态资源,再返回给浏览器,浏览器进行解析*例如:servlet/jsp ...

四、tomcat设计原理

在这里插入图片描述

五、实现tomcat对静态资源的访问

(1).创建maven项目

在这里插入图片描述
在这里插入图片描述

(2).tomcat启动阶段

配置HttpServlet

创建HttpServletRequest接口

public interface HttpServletRequest {public String getUrl();public void setUrl(String url);public String getMethod();public void setMethod(String method);
}

创建HttpServletResponse接口

public interface HttpServletResponse {void write(String context) throws IOException;
}

创建HttpServlet

/*** class HttpServlet*/
public abstract class HttpServlet {public abstract void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException;public abstract void doPost(HttpServletRequest request,HttpServletResponse response);/*** HttpServlet 实现service方法*/public void service(HttpServletRequest request,HttpServletResponse response) throws IOException {if("GET".equals(request.getMethod())){doGet(request,response);}else if("POST".equals(request.getMethod())){doPost(request,response);}}}

创建工具类,描述返回的信息

/*** 返回信息工具类*/
public class ResponseUtil {public  static  final String responseHeader200 = "HTTP/1.1 200 \r\n"+"Content-Type:text/html \r\n"+"\r\n";public static String getResponseHeader404(){return "HTTP/1.1 404 \r\n"+"Content-Type:text/html \r\n"+"\r\n" + "404";}public static String getResponseHeader200(String context){return "HTTP/1.1 200 \r\n"+"Content-Type:text/html \r\n"+"\r\n" + context;}
}

配置注解信息

@Retention(RetentionPolicy.RUNTIME)  //注解的生命周期,运行期间保留
@Target(value = {ElementType.TYPE,ElementType.FIELD}) // 该注解作用在类上边
public @interface WebServlet {String urlMapping() default ""; //自定义的servlet路径
}

配置servlet容器

创建ServletConfig存储注解信息

/*** 注解上的信息*/
public class ServletConfig {private String urlMapping; //2.urlprivate String classpath; //3.类的全路径名public ServletConfig(String urlMapping,String classpath){this.classpath = classpath;this.urlMapping = urlMapping;}public String getUrlMapping() {return urlMapping;}public void setUrlMapping(String urlMapping) {this.urlMapping = urlMapping;}public String getClasspath() {return classpath;}public void setClasspath(String classpath) {this.classpath = classpath;}
}

工具类,获取servlet的全路径名

/*** 扫描指定包,获取该包下所有的类的全路径信息*/
public class SearchClassUtil {public static  List<String> classPaths = new ArrayList<String>();public static List<String> searchClass(){//需要扫描的包名String basePack = "com.qcby.webapp";//将获取到的包名转换为路径String classPath = SearchClassUtil.class.getResource("/").getPath();basePack =  basePack.replace(".", File.separator);String searchPath = classPath + basePack;doPath(new File(searchPath),classPath);//这个时候我们已经得到了指定包下所有的类的绝对路径了。我们现在利用这些绝对路径和java的反射机制得到他们的类对象return classPaths;}/*** 该方法会得到所有的类,将类的绝对路径写入到classPaths中* @param file*/private static void doPath(File file,String classpath) {if (file.isDirectory()) {//文件夹//文件夹我们就递归File[] files = file.listFiles();for (File f1 : files) {doPath(f1,classpath);}} else {//标准文件//标准文件我们就判断是否是class文件if (file.getName().endsWith(".class")) {String path = file.getPath().replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");//如果是class文件我们就放入我们的集合中。classPaths.add(path);}}}public static void main(String[] args) {List<String> classes = SearchClassUtil.searchClass();for (String s: classes) {System.out.println(s);}}
}

创建ServletConfigMapping生成servlet容器

/***  servlet容器*/
public class ServletConfigMapping {//定义一个集合用来存储自定义servlet的配置信息private static List<ServletConfig> configs = new ArrayList<>();//定义servlet容器public static Map<String,Class<HttpServlet>> classMap = new HashMap<>();//解析注解 ---- 为了实现当mytomcat类启动的时候就将webapp下边所有的类的注解信息获取到我们需要写一个static代码块static {//1.获取webapp包下有哪些类List<String> classPaths = SearchClassUtil.searchClass();//2.获取类的注解信息for (String classpath: classPaths) {try {//利用反射获取类的注解信息getMessage(classpath);} catch (ClassNotFoundException e) {e.printStackTrace();}}}//利用反射获取类的注解信息public static void getMessage(String classPath) throws ClassNotFoundException {Class clazz = Class.forName(classPath);//注解对象WebServlet webServlet = (WebServlet) clazz.getDeclaredAnnotation(WebServlet.class);//将解析的信息放入到集合当中configs.add(new ServletConfig(webServlet.urlMapping(),classPath));}//初始化类容器public static void initServlet() throws ClassNotFoundException {for (ServletConfig servletConfig: configs) {// 将servlet对象和 url请求地址放入到 map集合当中去classMap.put(servletConfig.getUrlMapping(), (Class<HttpServlet>) Class.forName(servletConfig.getClasspath()));}}
}

(3).接收前端请求

创建Request类接收前端数据并实现HttpServletRequest接口

public class Request implements HttpServletRequest {//请求的地址private String url;//请求的方式private String Method;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getMethod() {return Method;}public void setMethod(String method) {Method = method;}
}

创建Response类用来实现HttpServletResponse

public class Response implements HttpServletResponse {//输出流private OutputStream outputStream;public Response(OutputStream outputStream){this.outputStream = outputStream;}/*** 返回动态资源* @param context*/public void write(String context) throws IOException {outputStream.write(context.getBytes());}/*** 返回静态资源*/public void writeHtml(String path) throws Exception {String resourcesPath = FileUtil.getResoucePath(path);File file = new File(resourcesPath);if(file.exists()){//静态文件存在System.out.println("静态文件存在");FileUtil.writeFile(file,outputStream);}else {System.out.println("静态文件不存在");write(ResponseUtil.getResponseHeader404());}}
}

工具类获取静态资源

/*** 该类的主要作用是进行读取文件*/
public class FileUtil {public  static  boolean witeFile(InputStream inputStream, OutputStream outputStream){boolean success = false ;BufferedInputStream bufferedInputStream ;BufferedOutputStream bufferedOutputStream;try {bufferedInputStream = new BufferedInputStream(inputStream);bufferedOutputStream = new BufferedOutputStream(outputStream);bufferedOutputStream.write(ResponseUtil.responseHeader200.getBytes());int count = 0;while (count == 0){count = inputStream.available();}int fileSize = inputStream.available();long written = 0;int beteSize = 1024;byte[] bytes = new byte[beteSize];while (written < fileSize){if(written + beteSize > fileSize){beteSize = (int)(fileSize - written);bytes = new byte[beteSize];}bufferedInputStream.read(bytes);bufferedOutputStream.write(bytes);bufferedOutputStream.flush();written += beteSize;}success = true;} catch (IOException e) {e.printStackTrace();}return success;}public static boolean writeFile(File file,OutputStream outputStream) throws Exception{return witeFile(new FileInputStream(file),outputStream);}public static String getResoucePath(String path){String resource = FileUtil.class.getResource("/").getPath();return resource + "\\" + path;}}

获取输入流信息,获取访问方式和访问地址

public class MyTomcat {Request request = new Request();//启动tomcat主方法public void startUp() throws IOException, ClassNotFoundException {//1.定义socket对象,监听8080端口ServerSocket serverSocket = new ServerSocket(8080);while (true){Socket socket = serverSocket.accept();//等待接收 BIOSystem.out.println("有用户请求过来了.....");// 给每一个请求都开启一个线程处理信息new Thread(new Runnable() {@Overridepublic void run() {try {杜凯(socket);} catch (Exception e) {e.printStackTrace();}}}).start();}}//2.创建出入流,读取用户请求信息public void 杜凯(Socket socket) throws Exception {//创建输入流InputStream inputStream = socket.getInputStream();//解析输入流getInputStream(inputStream);socket.close();}public void getInputStream(InputStream inputStream) throws IOException {//将bit流转为文字信息int count = 0;while (count == 0){count = inputStream.available();}byte[] bytes = new byte[count];inputStream.read(bytes);String Context = new String(bytes);System.out.println(Context);//解析数据if(Context.equals("")){System.out.println("你输入了一个空请求");}else {String firstLine = Context.split("\\n")[0]; //根据换行来获取第一行数据request.setUrl(firstLine.split("\\s")[1]);request.setMethod(firstLine.split("\\s")[0]);}}public static void main(String[] args) throws IOException, ClassNotFoundException {MyTomcat myTomcat = new MyTomcat();myTomcat.startUp();}}

加载tomcat启动配置,判断访问内容时否是静态资源

public class MyTomcat {Request request = new Request();/*** servlet分发器* @param request* @throws InstantiationException* @throws IllegalAccessException*/public void dispatch(Request request, Response response) throws Exception {//根据请求的信息来获取servlet类Class<HttpServlet> servletClass = ServletConfigMapping.classMap.get(request.getUrl());//真实的创建servlet对象if(servletClass !=null){HttpServlet servlet =  servletClass.newInstance();servlet.service(request,response);}else {response.write(ResponseUtil.getResponseHeader404());}}//启动tomcat主方法public void startUp() throws IOException, ClassNotFoundException {//加载servlet信息ServletConfigMapping.initServlet();//1.定义socket对象,监听8080端口ServerSocket serverSocket = new ServerSocket(8080);while (true){Socket socket = serverSocket.accept();//等待接收 BIOSystem.out.println("有用户请求过来了.....");// 给每一个请求都开启一个线程处理信息new Thread(new Runnable() {@Overridepublic void run() {try {杜凯(socket);} catch (Exception e) {e.printStackTrace();}}}).start();}}//2.创建出入流,读取用户请求信息public void 杜凯(Socket socket) throws Exception {//创建输入流InputStream inputStream = socket.getInputStream();//解析输入流getInputStream(inputStream);//输出流Response response = new Response(socket.getOutputStream());//根据url判断是静态资源还是动态资源if(request.getUrl().equals("")){//没有访问数据response.write(ResponseUtil.getResponseHeader404());}else if(ServletConfigMapping.classMap.get(request.getUrl()) == null){//访问静态资源response.writeHtml(request.getUrl());}else {//访问动态资源dispatch(request,response);}socket.close();}public void getInputStream(InputStream inputStream) throws IOException {//将bit流转为文字信息int count = 0;while (count == 0){count = inputStream.available();}byte[] bytes = new byte[count];inputStream.read(bytes);String Context = new String(bytes);System.out.println(Context);//解析数据if(Context.equals("")){System.out.println("你输入了一个空请求");}else {String firstLine = Context.split("\\n")[0]; //根据换行来获取第一行数据request.setUrl(firstLine.split("\\s")[1]);request.setMethod(firstLine.split("\\s")[0]);}}public static void main(String[] args) throws IOException, ClassNotFoundException {MyTomcat myTomcat = new MyTomcat();myTomcat.startUp();}}

相关文章:

用BIO实现tomcat

一、前言 本课程的难度较高&#xff0c;需要将Servlet原理和IO课程全部学完。 二、当前项目使用方式 (1).自定义servlet 自定义servlet需要实现WebServlet并且实现name和urlMapping 重启进行访问 http://localhost:8090/myServlet (2).自定义html 重启进行访问 http://loc…...

JS逆向进阶篇【去哪儿旅行登录】【下篇-逆向Bella参数JS加密逻辑Python生成】

目录&#xff1a; 每篇前言&#xff1a;引子——本篇目的1、 代码混淆和还原&#xff08;1&#xff09;单独替换&#xff1a;&#xff08;2&#xff09;整个js文件替换&#xff1a; 2、算法入口分析3、 深入分析&#xff08;0&#xff09;整体分析&#xff1a;&#xff08;1&am…...

【机器学习】生成对抗网络GAN

概述 生成对抗网络&#xff08;Generative Adversarial Network&#xff0c;GAN&#xff09;是一种深度学习模型架构&#xff0c;由生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discriminator&#xff09;两部分组成&#xff0c;旨在通过对抗训练的方式生成逼…...

centos7安装kafka、zookeeper

安装jdk 安装jdk8 安装zookeeper 在指定目录执行下载命令 我是在/newdisk/zookeeper目录下 wget https://archive.apache.org/dist/zookeeper/zookeeper-3.5.8/apache-zookeeper-3.5.8-bin.tar.gz --no-check-certificate下载好后并解压 tar -zxvf apache-zookeeper-3.5…...

基于 STM32U5 片内温度传感器正确测算温度

目录预览 1、引言 2、问题 3、小结 01 引言 STM32 在内部都集成了一个温度传感器&#xff0c;STM32U5 也不例外。这个位于晶圆上的温度传感器虽然不太适合用来测量外部环境的温度&#xff0c;但是用于监控晶圆上的温度还是挺好的&#xff0c;以防止芯片过温运行。 02 问题…...

【比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据】操作批量新增、分页查询(三)

orm框架使用性能比较 比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据 环境&#xff1a; idea jdk17 spring boot 3.0.7 mysql 8.0测试条件常规对象 orm 框架是否支持xml是否支持 Lambda对比版本mybatis☑️☑️3.5.4sqltoy☑️☑️5.2.98lazy✖️☑️1.2.4…...

Leetcode 3068. Find the Maximum Sum of Node Values

Leetcode 3068. Find the Maximum Sum of Node Values 1. 解题思路2. 代码实现 题目链接&#xff1a;3068. Find the Maximum Sum of Node Values 1. 解题思路 这一题虽然标记为一道hard的题目&#xff0c;但其实就是一个脑筋急转弯的题目。 我们只需要想明白一点即可&…...

用 Dockerfile为镜像添加SSH服务

1、基础镜像ubuntu:18.04 2、替换为国内的安装源 3、安装openssh-server 4、允许root用户远程登陆 5、暴露端口22 6、服务开机自启动 1.创建目录 [rootopenEuler-node1 db]# mkdir sshd_ubuntu 2.创建 Dockerfile、 run.sh 、authorized_keys、vim aliyun.list 文件 [rootop…...

Maven能解决什么问题?为什么要用?

如果没有maven&#xff0c;我们在开发一个应用的时候&#xff0c;需要自己先确定要引入哪些第三方的jar包&#xff0c;并且要去找到这些jar包&#xff0c;把他们导入到项目中&#xff0c;而且最痛苦的时候各个jar包之间的兼容性和冲突的问题。 jar包弄好了之后&#xff0c;我们…...

【Golang星辰图】探索网络和HTTP的奇妙世界:使用Go语言打造高性能应用

提升Web开发效率&#xff1a;学会使用Go语言的网络和HTTP库 前言 随着互联网的快速发展&#xff0c;网络和HTTP成为了现代应用开发中必不可少的部分。Go语言作为一门快速、可靠和高效的编程语言&#xff0c;提供了丰富的网络编程和HTTP处理库&#xff0c;使得构建高性能的网络…...

[C语言]——操作符

目录 一.算术操作符&#xff1a;、-、*、/、% 1. 和 - 2.* 3./ 4.% 二.赋值操作符&#xff1a;和复合赋值 1.连续赋值 2.复合赋值符 三.单目操作符&#xff1a;、--、、- 1.和-- 1.1前置 1.2后置 1.3前置-- 2. 和 - 四.强制类型转换 一.算术操作符&#xff1a;…...

iview碰到的一些问题总结

iview tabs嵌套使用问题 tabs嵌套使用的时候不是直接套用行了&#xff0c;直接套用会出现内层tab都集成到一级tab去&#xff0c;需要设置该属性指向对应 Tabs 的 name 字段(需要版本大于3.3.1) <Tabs name"tab1" ><TabPane label"标签1" tab&qu…...

【Python笔记-FastAPI】后台任务+WebSocket监控进度

目录 一、代码示例 二、执行说明 (一) 调用任务执行接口 (二) 监控任务进度 实现功能&#xff1a; 注册后台任务&#xff08;如&#xff1a;邮件发送、文件处理等异步场景&#xff0c;不影响接口返回&#xff09;监控后台任务执行进度&#xff08;进度条功能&#xff09;支…...

力扣hot100:15.三数之和(双指针/哈希表)

分析&#xff1a; 三数和问题&#xff0c;这里和两数之和不一样&#xff0c;返回的是值&#xff0c;因此可以对其进行排序&#xff0c;使用双指针。 一、一层循环双指针 class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {sort…...

VMware虚拟机使用Windows共享的文件夹

虚拟机版本为 VMware Workstation 16 Pro:16.2.4&#xff1b;主机位Windows11&#xff1b;记录于2024-03-05   在个人使用时&#xff0c;经常会有一些数据集等大文件重复在不同实验中使用&#xff0c;但是不同系统中来回使用会导致占用虚拟机空间&#xff0c;该博文通过将主机…...

利用Python自动化日常任务

在快节奏的现代生活中&#xff0c;时间就是一切。幸运的是&#xff0c;Python提供了一系列强大的库和工具&#xff0c;可以帮助我们自动化那些乏味且重复的任务&#xff0c;从而释放我们的时间&#xff0c;让我们可以专注于更有创造性和有意义的工作。下面&#xff0c;我们将探…...

Android的多线程和异步处理

在Android开发中&#xff0c;多线程和异步处理是处理耗时操作、提高应用响应性和性能的关键技术。以下是一些关于Android多线程和异步处理的基本概念和实践&#xff1a; 1. **主线程&#xff08;UI线程&#xff09;**&#xff1a; - Android应用的主线程负责处理UI操作和事…...

MySQL-----视图

一 视图 ▶ 介绍 视图view是一个虚拟表&#xff0c;非真实存在&#xff0c;其本质是根据SQL语句获取动态的数据集&#xff0c;并为其命名&#xff0c;用户使用时只需使用视图名称即可获取结果集&#xff0c;并可以将其当作表来使用。 数据库中存放了视图的定义&…...

LeetCode-02

225. 用队列实现栈 用两个队列实现栈的功能&#xff0c;思路如下&#xff1a; 往空队列中放新元素把非空队列中的元素依次放入刚才添加了新元素的队列&#xff0c;直到非空队列变为空队列 class MyStack(object):def __init__(self):self.queue1 []self.queue2 []def push(…...

瑞_Redis_Redis的Java客户端

文章目录 1 Redis的Java客户端1.1 Jedis快速入门1.1.1 入门案例1.1.1.1 项目构建1.1.1.2 引入依赖1.1.1.3 建立连接1.1.1.4 释放资源1.1.1.5 测试1.1.1.6 完整测试类代码 1.1.2 Jedis连接池1.1.2.1 连接池工具类1.1.2.2 改造原始代码 1.2 SpringDataRedis1.2.1 RedisTemplate1.…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...