用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();}}

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

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

相关文章

【C++ 编程指南】

C 编程指南 ■ C环境安装■ C 基本语法■ 预定义宏■ # 和 ## 运算符■ C 引用■ C 命名空间■ 定义命名空间■ using 指令■ 嵌套的命名空间 ■ String类■ 类■ 类的static静态成员 ■ C 继承■ 继承类型 public、protected 或 private■ 访问控制和继承■ 多继承■ 数据抽象…

最新版阿里云Linux CentOS7 ecs-user用户安装Mysql8详细教程(超简单)

经过两天的踩坑后&#xff0c;终于成功安装&#xff0c;并找到了最快捷的安装方式。接下来就由我来给大家介绍不踩坑安装大法&#xff01; 一、下载Mysql 首先前往Mysql官网下载 MySQL官方下载地址 第一步&#xff0c;选择安装包&#xff0c;这是最关键的一步&#xff0c;选错安…

css样式元素的相对定位,绝对定位,固定定位等元素定位运用技巧详解

文章目录 1.相对定位 relative2.绝对定位 absolute3.固定定位4.display 转换元素5.float浮动6.float产生内容塌陷问题7.overflow CSS样式学习宝典&#xff0c;关注点赞加收藏&#xff0c;防止迷路哦 在CSS中关于定位的内容是&#xff1a;position:relative | absolute | static…

uniapp聊天记录本地存储(详细易懂)

目录 目录 1、通过websocket拿取数据 2、获取聊天数据 3、聊天信息存储 、更新 4、读取聊天记录 5、发送信息&#xff0c;信息获取 6、最终效果 1.聊天信息的存储格式 2、样式效果 写聊天项目&#xff0c;使用到了本地存储。需要把聊天信息保存在本地&#xff0c;实时获…

第105讲:Mycat垂直分表实战:从规划到解决问题的完整指南

文章目录 1.垂直分表的背景2.垂直分表案例实战2.1.垂直分表规划2.2.配置Mycat实现垂直分表2.3.重启Mycat2.4.在Mycat命令行中导入数据结构2.5.查看由Mycat分表后每个分片上存储的表2.6.Mycat垂直分表后可能遇到的问题2.7.垂直分表完成 1.垂直分表的背景 我们的商城系统数据库&…

软件测试项目实战,某购物车/测试点分析实战(详细步骤)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 第一步&#xff1…

winform 输出运行设备的mac地址

winform定制一个代码段 输出运行设备的mac码此方法获取的是运行设备上的物理网卡的MAC地址&#xff0c;并不包括虚拟网卡或无线网卡的MAC地址。当设备具有多个网卡时&#xff0c;它只返回第一个正常运行的网卡的MAC地址。如果未找到任何网卡&#xff0c;则返回"未找到MAC地…

贪心(基础算法)--- 区间选点

905. 区间选点 思路 &#xff08;贪心&#xff09;O(nlogn) 根据右端点排序 将区间按右端点排序 遍历区间&#xff0c;如果当前区间左端点不包含在前一个区间中&#xff0c;则选取新区间&#xff0c;所选点个数加1&#xff0c;更新当前区间右端点。如果包含&#xff0c;则跳…

雅特力AT32L021首款低功耗MCU震撼登场

雅特力于2月28日正式发布AT32L021首款入门级低功耗MCU&#xff0c;搭配不同容量Flash、SRAM&#xff0c;提供7种封装类型共21个型号选择&#xff0c;最小封装面积仅3x3mm。为降低能耗&#xff0c;延长设备运作时间&#xff0c;AT32L021系列支持多种能耗模式和休眠模式&#xff…

韦东山嵌入式Liunx入门驱动开发五

文章目录 一、驱动程序基石1-1 休眠与唤醒1-2 POLL机制1-3 异步通知(1) 异步通知程序解析(2) 异步通知机制内核代码详解 1-4 阻塞与非阻塞1-5 定时器(1) 内核函数(2) 定时器时间单位 1-6 中断下半部 tasklet 本人学习完韦老师的视频&#xff0c;因此来复习巩固&#xff0c;写以…

【活动】前端世界的“祖传代码”探秘:从古老魔法到现代重构

作为一名前端工程师&#xff0c;我时常在项目中邂逅那些被岁月打磨过的“祖传代码”。它们就像古老的魔法书页&#xff0c;用HTML标签堆砌起的城堡、CSS样式表中的炼金术&#xff0c;以及JavaScript早期版本中舞动的符咒。这些代码承载着先驱们的探索精神和独特智慧&#xff0c…

#FPGA(基础知识)

1.IDE:Quartus II 2.设备&#xff1a;Cyclone II EP2C8Q208C8N 3.实验&#xff1a;正点原子-verilog基础知识 4.时序图&#xff1a; 5.步骤 6.代码&#xff1a;

专业145+总分410+西工大西北工业大学827信号与系统考研经验电子信息与通信工程,海航,真题,大纲,参考书。

经过一年的努力&#xff0c;分数终于出来。今年专业课827信号与系统145&#xff08;很遗憾差了一点点满分&#xff0c;没有达到Jenny老师的最高要求&#xff09;&#xff0c;数一130&#xff0c;英语和政治也都比较平衡&#xff0c;总分410分&#xff0c;当然和信息通信考研Jen…

【Git】深入理解 Git 分支合并操作:git merge dev 命令详解

深入理解 Git 合并操作&#xff1a;git merge dev 命令详解 摘要&#xff1a;本文将深入探讨 Git 中的合并操作&#xff0c;以及如何使用 git merge dev 命令将dev 分支的修改合并到当前分支&#xff08;假设当前分支为main 分支&#xff09;中。通过详细的解释和示意图&#x…

linux安全--DNS欺骗,钓鱼网站搭建

目录 一&#xff0c;实验准备 首先让client能上网 1&#xff09;实现全网互通&#xff0c;实现全网互通过程请看 2&#xff09;SNAT源地址转换 3&#xff09;部署DHCP服务 4)配置DHCP服务 5&#xff09;启动服务 6&#xff09;安装DNS服务 7&#xff09;DNS配置 8)启动DNS…

HOOPS Communicator对3D大模型轻量化加载与渲染的4种解决方案

今天给大家介绍一些关于3D Web轻量化引擎HOOPS Commuicator的关键概念&#xff0c;这些概念可以帮您在HOOPS Communicator流缓存服务器之上更好地构建您自己的模型流服务器。如果您是有大型数据集&#xff0c;那么&#xff0c;使用流缓存服务器可以极大地帮助您最大限度地减少内…

Unity 预制体与变体

预制体作用&#xff1a; 更改预制体&#xff0c;则更改全部的以预制体复制出的模型。 生成预制体&#xff1a; 当你建立好了一个模型&#xff0c;从层级拖动到项目中即可生成预制体。 预制体复制模型&#xff1a; 将项目中的预制体拖动到层级中即可复制。或者选择物体复制粘贴。…

Java基础 - 6 - 面向对象(二)

Java基础 - 6 - 面向对象&#xff08;一&#xff09;-CSDN博客 二. 面向对象高级 2.1 static static叫做静态&#xff0c;可以修饰成员变量、成员方法 2.1.1 static修饰成员变量 成员变量按照有无static修饰&#xff0c;分为两种&#xff1a;类变量、实例变量&#xff08;对象…

VL53L8CX驱动开发(1)----驱动TOF进行区域检测

VL53L8CX驱动开发----1.驱动TOF进行区域检测 概述视频教学样品申请源码下载主要特点硬件准备技术规格系统框图应用示意图区域映射生成STM32CUBEMX选择MCU 串口配置IIC配置LPn 设置X-CUBE-TOF1串口重定向代码配置Tera Term配置演示结果 概述 VL53L8CX是一款8x8多区域ToF测距传感…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--强化学习

专属领域论文订阅 关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新论文。 分类: 大语言模型LLM视觉模型VLM扩散模型视觉…