手写Tomcat,我们起名叫Minicat,完成以下功能,作为一个服务器软件提供服务,可以通过浏览器发送http请求,Minicat可以接收到请求进行处理,处理之后结果返回给客户端
|
- 提供服务,接收请求(Socket通信)
- 请求信息封装成Request对象(Respnse对象)
- 客户端请求资源,资源分为静态资源(html)和动态资源(Servlet)
- 资源返回给客户端浏览器
由简单到复杂,我们将其分为4个版本1.0,2.0,3.0,multithreading
|
- 1.0版本:浏览器请求http://localhost:8080,返回一个固定的字符串到页面"Hello Minicat!!!"
- 2.0版本:封装Request和Response对象,返回html静态资源文件
- 3.0版本:处理返回动态资源Servlet
- 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,我们将其封装到方法中
|
- 网页提示响应无效ERR_INVALID_HTTP_RESPONSE错误的HTTP响应
- http协议规定了,我们请求和响应的请求/响应头、请求/响应体
- 格式不正确的话,浏览器没法正常解析
2. 响应信息封装成Respnse对象(http)
1. 我们将响应头信息,封装成一个工具类(只简单提供响应码为200和404的情况)
|
- 我们先看下百度的响应头
- 封装自己的,我们只封装必须的一些参数
二、Minicat2.0版本
封装Request和Response对象,返回html静态资源文件
|
- 为了加以区分,我将各版本分开存放
1. 获取请求信息
- 修改start()方法,根据InputStream获取信息
- 测试
2. 封装Request和Response
1. 封装Request获取请求方式和url,封装Response,根据url获取静态html文件,输出
|
- Request
- 封装Response对象之前,我们要响应静态资源,可以单独将处理静态资源的逻辑封装成工具类
- 封装Response对象
2. 编写index.html,用户请求后,将html输出
|
- 修改start()方法,调用我们封装好的工具类
- 编写html,运行Minicat,保证html页面被编译
三、Minicat3.0版本
- 为了加以区分,我将各版本分开存放
1. 实现自己的Servlet
- Servlet接口,制定servlet基本规范
- HttpServlet抽象类,对servlet做一定抽象封装
- 自己写Servlet,处理业务
2. 加载解析Servlet配置(web.xml)
- web.xml
- 添加依赖
- 重写Minicat启动类,添加一个map存储url和Servlet类的映射,添加解析处理xml文件配置的方法
3. 接收处理请求,测试
- 改造start()方法,判断请求url,如果是Servlet映射,就是动态请求,否则就是请求静态资源
- 启动Minicat测试
四、解析问题,多线程改造
对于多线程不了解的同学可以粗略浏览下我们另外两篇文章
|
- 线程基本知识:https://blog.csdn.net/grd_java/article/details/109680187
- JUC锁,一些面试题和源码讲解:https://blog.csdn.net/grd_java/article/details/112979163
- 高并发多线程容器,线程池:https://blog.csdn.net/grd_java/article/details/113116244
- 为了加以区分,我将各版本分开存放
1. Minicat3.0的问题
我们希望,每个用户访问Minicat,是独立的,互不影响的,不能出现用户2等待用户1的情况
|
- 下面我们模拟两个用户同时访问服务器
- 用户A先请求/myServlet,但是处理时间有些长
- 用户B又来请求index.html,但是会因为用户A的请求没处理完,而等待
- 我们为Servlet添加一段代码Thread.sleep(100000);//休眠100000ms,模拟一个Servlet处理时间较长的情景
- 我们请求/myServlet,因为线程休眠时间很长,所以我们在等待它运行完成
- 我们再请求/index.html,此时访问静态资源,也需要等待前面的Servlet处理完成
因为现在的Minicat,逻辑都是跑在主线程(main)中的,就是一个单线程,只能处理完一个,下一个才能继续处理
|
- 那么我们就让逻辑跑在多个线程中
- 也就是将start() 多线程化
2. 线程改造
3. 使用线程池优化
每次来一个请求都创建一个线程出来,有点太过土豪,所以我们通过线程池管理线程,请求来了,从线程池拿线程,用完放回去,这样提高线程复用性
|
- 就像我们平常吃饭,每次用一次性筷子,太浪费木头了
- 一般家里的筷子都是用完洗,洗完放回收纳盒,下次接着用
- 我用的线程池是ThreadPoolExecutor,我从以前写到文章截取这个线程池的解析
- 提供一个方法,创建线程池ThreadPoolExecutor
实现自己的Tomcat、Servlet、多线程(线程池)处理请求相关推荐
- 干货 | Tomcat 连接数与线程池详解
转载自 干货 | Tomcat 连接数与线程池详解 前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在 ...
- 多线程线程池的实现java_如何在Java中实现线程池
多线程线程池的实现java 线程是独立程序的执行路径. 在java中,每个线程都扩展java.lang.Thread类或实现java.lang.Runnable. 多线程是指在一个任务中同时执行两个或 ...
- 多线程线程池的基本创建,使用方法
import java.util.concurrent.*;/*** 多线程线程池的基本创建,使用方法** @author silence*/ public class Silence {public ...
- java异步线程池同时请求多个接口数据
java异步线程池同时请求多个接口数据 一.适合的使用场景 复杂的网页爬虫,如要同时请求多个不同网页的数据,并且需要执行不同的数据处理,这个是非常合适的,执行线程传递的参数到最后callback是会附 ...
- Tomcat中的线程池(APR和ThreadPool)
一.容器简化了程序员自身的多线程编程. 各种Web容器,如Tomcat,Resion,Jetty等都有自己的线程池(可在配置文件中配置),所以在客户端进行请求调用的时候,程序员不用针对Client的每 ...
- java 线程池 初始大小_为什么tomcat的默认线程池大小如此之大? - java
我注意到默认的tomcat 7线程池大小似乎是200. 但是普通的CPU似乎有16个内核. 因此只能并行执行16个线程 为什么tomcat使用那么多线程. 参考方案 多年以来,许多单核计算机问世,并且 ...
- 【Java从入门到头秃专栏 6】语法篇(五) :多线程 线程池 可见、原子性 并发包 Lambda表达式
目录 1 多线程 1.1 基本概念 1.2 创建线程的三种方式 1.4 解决线程安全问题的三种方法 1.5 线程通信 1.6 线程状态 2 线程池 2.1线程池的概念 2.2 创建并提交任务 3 可见 ...
- 一心多用多线程-线程池ThreadPoolExecutor-看这篇就够了
许久之前理解了java线程池ThreadPoolExecutor,今天来做一个总结,根据java api加上自己的理解,让我们能更透彻的理解java线程池 首先先写一下线程池的概念: 线程池:线程池是 ...
- Java多线程 线程池Executor框架
目录 一.说明 二.理解 Executor ExecutorService Executors 三.实现 1. newSingleThreadExecutor 2. newFixedThreadPoo ...
- 多线程---线程池的使用
线程池的使用 一.Executors - 线程池的工厂 二.JDK自带的一些线程池 1. SingleThreadExecutor 2. FixThreadPool 3. CachedThreadPo ...
最新文章
- 汇编html文档,欢迎走进HTML的世界汇编.ppt
- react todolist代码优化
- 【Django】Django Debug Toolbar调试工具配置
- ASP.NET中XML数据的处理
- java监听鼠标接口实现_自定义Java鼠标监听器?
- chrome webstore
- 如何找出电脑里的流氓软件_可怕:正版的流氓软件,100个人的电脑里99台都安装了...
- PLT图纸外发控制系统
- 外汇交易:哪个货币对比较好做?
- HTML压缩(JSP的GZIP实现)
- 1、vsftpd的简介
- 知行:成长的迭代之路
- 凸优化笔记6(共轭梯度法)
- 亚马逊FBA基本介绍
- Splus—基于AIR的Sina微博客户端
- mysql mdl 锁_MySQL源码学习:MDL字典锁
- 漫画小说CMS系统源码
- 【Java】(二十四)File类(文件操作,文件夹操作,FileFilter接口);Properties属性集合
- 完美解决Cisco Packet Tracer 7.0需要账号登录的登录问题
- After effect重装时文件没删除干净
热门文章
- 2010宅男腐女们的杯洗具签名
- python b站 排行_Python爬虫抓取B站小视频排行榜,新手也可以跟着做哦!
- Android超简单底部导航ImageView+TextView+FramLayout(一)
- ibm linux网络配置命令,MQ安装笔记
- quarkus数据库篇之一:比官方demo更简单的基础操作
- 教你一招:如何快速制作来访登记二维码?
- unbuntu 中远程桌面连接 tab键不能用
- Hibernate从0开始,入门到放弃,一文上手
- Python 爬虫实例(6)—— 爬取蚂蚁免费代理
- 应用跳转(打电话/短信/邮件/浏览器/其他应用)