手写Tomcat,我们起名叫Minicat,完成以下功能,作为一个服务器软件提供服务,可以通过浏览器发送http请求,Minicat可以接收到请求进行处理,处理之后结果返回给客户端
  1. 提供服务,接收请求(Socket通信)
  2. 请求信息封装成Request对象(Respnse对象)
  3. 客户端请求资源,资源分为静态资源(html)和动态资源(Servlet)
  4. 资源返回给客户端浏览器
由简单到复杂,我们将其分为4个版本1.0,2.0,3.0,multithreading
  1. 1.0版本:浏览器请求http://localhost:8080,返回一个固定的字符串到页面"Hello Minicat!!!"
  2. 2.0版本:封装Request和Response对象,返回html静态资源文件
  3. 3.0版本:处理返回动态资源Servlet
  4. multithreading: 多线程版
源码(Gitee码云):https://gitee.com/yin_zhipeng/implement-_tomcat_of_myself.git
准备工作

1. 建立maven项目引入依赖

<build><plugins><!--指定编译级别--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><!--加个插件--><version>3.1</version><configuration><source>8</source><!--JDK--><target>8</target><!--编译--><encoding>utf-8</encoding><!--编码--></configuration></plugin></plugins>
</build>

文章目录

  • 一、Minicat1.0版本
    • 1. 提供服务,接收请求(Socket通信)
    • 2. 响应信息封装成Respnse对象(http)
  • 二、Minicat2.0版本
    • 1. 获取请求信息
    • 2. 封装Request和Response
  • 三、Minicat3.0版本
    • 1. 实现自己的Servlet
    • 2. 加载解析Servlet配置(web.xml)
    • 3. 接收处理请求,测试
  • 四、解析问题,多线程改造
    • 1. Minicat3.0的问题
    • 2. 线程改造
    • 3. 使用线程池优化

一、Minicat1.0版本

实现浏览器请求http://localhost:8080,返回一个固定的字符串到页面"Hello Minicat!!!"

1. 提供服务,接收请求(Socket通信)

1. 首先玩Socket需要定义一个端口号,Tomcat是配在web.xml文件中,为了代码简洁我们直接定义主类里,后面自己实现Servlet的时候,会用web.xml解析Servlet

2. 有了端口号,想要程序启动,需要做一些初始化的程序,比如启动socket,我们将其封装到方法中

3. main函数测试

  1. 网页提示响应无效ERR_INVALID_HTTP_RESPONSE错误的HTTP响应
  2. http协议规定了,我们请求和响应的请求/响应头、请求/响应体
  3. 格式不正确的话,浏览器没法正常解析

2. 响应信息封装成Respnse对象(http)

1. 我们将响应头信息,封装成一个工具类(只简单提供响应码为200和404的情况)
  1. 我们先看下百度的响应头
  2. 封装自己的,我们只封装必须的一些参数
2. 修改响应内容,带上响应头

3. main测试

二、Minicat2.0版本

封装Request和Response对象,返回html静态资源文件
  1. 为了加以区分,我将各版本分开存放

1. 获取请求信息

  1. 修改start()方法,根据InputStream获取信息
  2. 测试

2. 封装Request和Response

1. 封装Request获取请求方式和url,封装Response,根据url获取静态html文件,输出
  1. Request

  2. 封装Response对象之前,我们要响应静态资源,可以单独将处理静态资源的逻辑封装成工具类

  3. 封装Response对象

2. 编写index.html,用户请求后,将html输出
  1. 修改start()方法,调用我们封装好的工具类
  2. 编写html,运行Minicat,保证html页面被编译

三、Minicat3.0版本

处理返回动态资源Servlet
  1. 为了加以区分,我将各版本分开存放

1. 实现自己的Servlet

  1. Servlet接口,制定servlet基本规范
  2. HttpServlet抽象类,对servlet做一定抽象封装
  3. 自己写Servlet,处理业务

2. 加载解析Servlet配置(web.xml)

  1. web.xml
  2. 添加依赖
  3. 重写Minicat启动类,添加一个map存储url和Servlet类的映射,添加解析处理xml文件配置的方法

3. 接收处理请求,测试

  1. 改造start()方法,判断请求url,如果是Servlet映射,就是动态请求,否则就是请求静态资源
  2. 启动Minicat测试

四、解析问题,多线程改造

对于多线程不了解的同学可以粗略浏览下我们另外两篇文章
  1. 线程基本知识:https://blog.csdn.net/grd_java/article/details/109680187
  2. JUC锁,一些面试题和源码讲解:https://blog.csdn.net/grd_java/article/details/112979163
  3. 高并发多线程容器,线程池:https://blog.csdn.net/grd_java/article/details/113116244
  1. 为了加以区分,我将各版本分开存放

1. Minicat3.0的问题

我们希望,每个用户访问Minicat,是独立的,互不影响的,不能出现用户2等待用户1的情况
  1. 下面我们模拟两个用户同时访问服务器
  2. 用户A先请求/myServlet,但是处理时间有些长
  3. 用户B又来请求index.html,但是会因为用户A的请求没处理完,而等待
  1. 我们为Servlet添加一段代码Thread.sleep(100000);//休眠100000ms,模拟一个Servlet处理时间较长的情景
  2. 我们请求/myServlet,因为线程休眠时间很长,所以我们在等待它运行完成
  3. 我们再请求/index.html,此时访问静态资源,也需要等待前面的Servlet处理完成
因为现在的Minicat,逻辑都是跑在主线程(main)中的,就是一个单线程,只能处理完一个,下一个才能继续处理
  1. 那么我们就让逻辑跑在多个线程中
  2. 也就是将start() 多线程化

2. 线程改造

1. 写一个线程类

2. 改造Minicat 的 start()方法

3. 测试

3. 使用线程池优化

每次来一个请求都创建一个线程出来,有点太过土豪,所以我们通过线程池管理线程,请求来了,从线程池拿线程,用完放回去,这样提高线程复用性
  1. 就像我们平常吃饭,每次用一次性筷子,太浪费木头了
  2. 一般家里的筷子都是用完洗,洗完放回收纳盒,下次接着用
1. 写一个方法,提供线程池
  1. 我用的线程池是ThreadPoolExecutor,我从以前写到文章截取这个线程池的解析
  2. 提供一个方法,创建线程池ThreadPoolExecutor
2. 使用线程池,改造start()方法

3. 测试

实现自己的Tomcat、Servlet、多线程(线程池)处理请求相关推荐

  1. 干货 | Tomcat 连接数与线程池详解

    转载自  干货 | Tomcat 连接数与线程池详解 前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在 ...

  2. 多线程线程池的实现java_如何在Java中实现线程池

    多线程线程池的实现java 线程是独立程序的执行路径. 在java中,每个线程都扩展java.lang.Thread类或实现java.lang.Runnable. 多线程是指在一个任务中同时执行两个或 ...

  3. 多线程线程池的基本创建,使用方法

    import java.util.concurrent.*;/*** 多线程线程池的基本创建,使用方法** @author silence*/ public class Silence {public ...

  4. java异步线程池同时请求多个接口数据

    java异步线程池同时请求多个接口数据 一.适合的使用场景 复杂的网页爬虫,如要同时请求多个不同网页的数据,并且需要执行不同的数据处理,这个是非常合适的,执行线程传递的参数到最后callback是会附 ...

  5. Tomcat中的线程池(APR和ThreadPool)

    一.容器简化了程序员自身的多线程编程. 各种Web容器,如Tomcat,Resion,Jetty等都有自己的线程池(可在配置文件中配置),所以在客户端进行请求调用的时候,程序员不用针对Client的每 ...

  6. java 线程池 初始大小_为什么tomcat的默认线程池大小如此之大? - java

    我注意到默认的tomcat 7线程池大小似乎是200. 但是普通的CPU似乎有16个内核. 因此只能并行执行16个线程 为什么tomcat使用那么多线程. 参考方案 多年以来,许多单核计算机问世,并且 ...

  7. 【Java从入门到头秃专栏 6】语法篇(五) :多线程 线程池 可见、原子性 并发包 Lambda表达式

    目录 1 多线程 1.1 基本概念 1.2 创建线程的三种方式 1.4 解决线程安全问题的三种方法 1.5 线程通信 1.6 线程状态 2 线程池 2.1线程池的概念 2.2 创建并提交任务 3 可见 ...

  8. 一心多用多线程-线程池ThreadPoolExecutor-看这篇就够了

    许久之前理解了java线程池ThreadPoolExecutor,今天来做一个总结,根据java api加上自己的理解,让我们能更透彻的理解java线程池 首先先写一下线程池的概念: 线程池:线程池是 ...

  9. Java多线程 线程池Executor框架

    目录 一.说明 二.理解 Executor ExecutorService Executors 三.实现 1. newSingleThreadExecutor 2. newFixedThreadPoo ...

  10. 多线程---线程池的使用

    线程池的使用 一.Executors - 线程池的工厂 二.JDK自带的一些线程池 1. SingleThreadExecutor 2. FixThreadPool 3. CachedThreadPo ...

最新文章

  1. 汇编html文档,欢迎走进HTML的世界汇编.ppt
  2. react todolist代码优化
  3. 【Django】Django Debug Toolbar调试工具配置
  4. ASP.NET中XML数据的处理
  5. java监听鼠标接口实现_自定义Java鼠标监听器?
  6. chrome webstore
  7. 如何找出电脑里的流氓软件_可怕:正版的流氓软件,100个人的电脑里99台都安装了...
  8. PLT图纸外发控制系统
  9. 外汇交易:哪个货币对比较好做?
  10. HTML压缩(JSP的GZIP实现)
  11. 1、vsftpd的简介
  12. 知行:成长的迭代之路
  13. 凸优化笔记6(共轭梯度法)
  14. 亚马逊FBA基本介绍
  15. Splus—基于AIR的Sina微博客户端
  16. mysql mdl 锁_MySQL源码学习:MDL字典锁
  17. 漫画小说CMS系统源码
  18. 【Java】(二十四)File类(文件操作,文件夹操作,FileFilter接口);Properties属性集合
  19. 完美解决Cisco Packet Tracer 7.0需要账号登录的登录问题
  20. After effect重装时文件没删除干净

热门文章

  1. 2010宅男腐女们的杯洗具签名
  2. python b站 排行_Python爬虫抓取B站小视频排行榜,新手也可以跟着做哦!
  3. Android超简单底部导航ImageView+TextView+FramLayout(一)
  4. ibm linux网络配置命令,MQ安装笔记
  5. quarkus数据库篇之一:比官方demo更简单的基础操作
  6. 教你一招:如何快速制作来访登记二维码?
  7. unbuntu 中远程桌面连接 tab键不能用
  8. Hibernate从0开始,入门到放弃,一文上手
  9. Python 爬虫实例(6)—— 爬取蚂蚁免费代理
  10. 应用跳转(打电话/短信/邮件/浏览器/其他应用)