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

手写简单的tomcat

首先,Tomcat是一个软件,所有的项目都能在Tomcat上加载运行,Tomcat最核心的就是Servlet集合,本身就是HashMap。Tomcat需要支持Servlet,所以有servlet底层的资源:HttpServlet抽象类、HttpRequest和HttpResponse,否则我们无法新建Servlet。

http协议:客户端和用户端进行请求和响应的过程:

这样我们就可以在webapps写项目了,一个项目有两大资源:servlet资源和静态资源,servlet本身是java类,我们让它调用doGet和doPost方法,必须继承HttpServlet,同时也需要@WebServlet注解,那么在Tomcat中就必须要有@WebServlet注解的实现,如果没有@WebServlet,我们就无法拿到相应的注解。这样我们就能成功搭建起Servlet资源。

当Http请求打过来之后,先打到socket上,处理Http请求,其本身就是连接器,从请求上能获取到请求路径和请求方法。先获取到请求路径,判断servlet容器中是否含有相同路径,如果有,再获取请求方法,判断是doGet还是doPost。


简易版tomcat的核心原理

真正的Tomcat很复杂,但它的最核心功能可以简化为:

  1. 监听HTTP请求(Socket 绑定 8080 端口)
  2. 解析HTTP请求(读取请求头、请求体)
  3. 找到对应的Servlet处理请求(反射调用 service() 方法)
  4. 返回HTTP响应(写回响应头和HTML)

手写tomcat

首先,定义Servlet接口

public interface servlet {public void service(HttpServletRequest request, HttpServletResponse response) throws IOException;
}

其次,定义request和response

public class HttpServletRequest {private String method;private String 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 class HttpServletResponse {//输出流private OutputStream outputStream;public HttpServletResponse(OutputStream outputStream){this.outputStream = outputStream;}/*** 返回动态资源* @param context*/public void write(String context) throws IOException {//System.out.println(context);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());}}}

然后,实现一个Httpserver

public class MyTomcat {static HashMap<String, HttpServlet> routes = TomcatRoute.routes; //tomcat路由\/*** 分发器*/public  void dispatch(HttpServletRequest request ,HttpServletResponse response) throws IOException {System.out.println("URL: " + request.getUrl());HttpServlet servlet = routes.get(request.getUrl());  //if(servlet!=null){ //说明请求的就是我们的servletSystem.out.println("找到匹配的Servlet: " + servlet.getClass().getName());servlet.service(request,response);}}/*** socket 启动* @throws IOException*/public  void start() throws IOException {ServerSocket serverSocket = new ServerSocket(8080);  //1.指定监听的端口号//2.对端口进行监听while (true){Socket socket = serverSocket.accept();//阻塞监听//3.打开输入流,解析客户端发来的内容InputStream inputStream = socket.getInputStream(); //输入流HttpServletRequest request = new HttpServletRequest();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));  //将字节流转换成字符流String str = reader.readLine();//分割request.setMethod(str.split("\\s")[0]);request.setUrl(str.split("\\s")[1]);//4.打开输出流OutputStream outputStream = socket.getOutputStream();HttpServletResponse response = new HttpServletResponse(outputStream);//分发器dispatch(request,response);socket.close();//socket在这里关闭}}//socketpublic static void main(String[] args) throws IOException {MyTomcat myTomcat = new MyTomcat();myTomcat.start();}
}

然后,自定义一个Servlet

@CYServlet(url = "/myServlet")
public class MyFirstServlet extends HttpServlet {@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) {super.doPost(request, response);}@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {System.out.println("Hello World!");System.out.println("Servlet实例: " + this);response.write(ResponseUtil.getResponseHeader200("hello world  hhhhh"));}
}

最后,启动服务并测试

public static void main(String[] args) throws IOException {MyTomcat myTomcat = new MyTomcat();myTomcat.start();}

访问浏览器localhost:8080会得到:

http://www.lryc.cn/news/2383929.html

相关文章:

  • 高等数学-积分
  • IOS平台Unity3D AOT全局模块结构分析
  • Vue 3.0中自定义指令
  • 在 语义分割 和 图像分类 任务中,image、label 和 output 的形状会有所不同。
  • C++面试4-sizeof解析
  • CyberSecAsia专访CertiK首席安全官:区块链行业亟需“安全优先”开发范式
  • uniapp如何设置uni.request可变请求ip地址
  • 文件操作和IO-3 文件内容的读写
  • 架构的设计
  • SpringAI 大模型应用开发篇-SpringAI 项目的新手入门知识
  • 编程速递-RAD Studio 12.3 Athens五月补丁:May Patch Available
  • Vue3实现轮播表(表格滚动)
  • Python爬虫(33)Python爬虫高阶:动态页面破解与验证码OCR识别全流程实战
  • Matlab学习合集
  • 基于labview的声音采集与存储分析系统
  • 【项目记录】部门增删改及日志技术
  • TDengine 更多安全策略
  • 电子制造企业智能制造升级:MES系统应用深度解析
  • Java使用Collections集合工具类
  • 磁盘空间不足,迁移Docker 数据目录
  • python打卡day33
  • 目标检测新突破:用MSBlock打造更强YOLOv8
  • 同城上门预约服务系统案例分享,上门服务到家系统都有什么功能?这个功能,很重要!
  • docker面试题(5)
  • 为什么需要在循环里fetch?
  • 用 UniApp 开发 TilePuzzle:一个由 CodeBuddy 主动驱动的拼图小游戏
  • HJ101 输入整型数组和排序标识【牛客网】
  • 在Linux debian12系统上使用go语言以及excelize库处理excel数据
  • Appium 的 enableMultiWindows 参数
  • 【Python/Tkinter】实现程序菜单