学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat
学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat
2019-05-09 19:28:42
注:项目(MyEclipse)创建的时候选择:Web Service Project
第一步 对Tomcat工作流程进行分析

第二步 对其项目进行全局的把关
首先看看Project(FirstTomcat)的目录结构
|-FirstTomcat
|——src
| |-org.mrzhangxd.com
| |-FirstRequest.java
| |-FirstResponse.java
| |-FirstServlet.java
| |-FirstTomcat.java
| |-FirstServletMapping.java
| |_FirstServletMappingConfig.java
| |-JRE System Library[JavaSE-x.y]
| |-JAXB x.y.z Libraries
| |-JavaEE x.y Generic Library
| |-JSTL x.y.z Library
| |-JAX-RS x.y Libraries(Project Jersey x.y)
|___|_WebRoot
第三步 代码实现
处理请求:
- 创建一个request对象并填充那些有可能被所引用的Servlet使用的信息,如参数,头部、cookies、查询字符串等。
- 创建一个response对象,所引用的servlet使用它来给客户端发送响应。
- 调用servlet的service方法,并传入request和response对象。这里servlet会从request对象取值,给response写值。
- 根据servlet返回的response生成相应的HTTP响应报文。
接下来一一实现
请求:FirstRequest.java
|
package org.mrzhangxd.com; import java.io.InputStream; /** * * @author mrzhangxd * */ public class FirstRequest { //请求路径 private String url; //请求方法 private String method; public FirstRequest(InputStream inputStream)throws Exception{ String httpRequest = ""; byte[] httpRequestBytes = new byte[1024]; int length = 0; if((length = inputStream.read(httpRequestBytes))>0){ httpRequest = new String(httpRequestBytes,0,length); } //HTTP请求协议:首行的内容依次为:请求方法、请求路径以及请求协议及其对应的版本号 //GET /index /HTTP/1.1 String httpHead = httpRequest.split("\n")[0];//取出HTTP协议的首行 System.out.println(httpHead); method = httpHead.split("\\s")[0];//按照空格进行分割,第一个请求方法
url = httpHead.split("\\s")[1];//按照空格进行分割,第二个是路径 System.out.println(this.toString()); }
public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String toString(){ return "MyRequest[url = "+url+",method = "+method+"]";
} } |
回应:FirstResponse.java
|
package org.mrzhangxd.com; import java.io.IOException; import java.io.OutputStream; /** * * @author mrzhangxd * */ public class FirstResponse { private OutputStream outputStream; public FirstResponse(OutputStream outputStream){ this.outputStream = outputStream; } //将文本转换为字节流 public void write(String content)throws IOException{ StringBuffer httpResponse = new StringBuffer(); httpResponse.append("HTTP/1.1 200 OK\n") .append("Content-Type;text/html\n") .append("\r\n") .append("<html><link rel = \"icon\"href = \"data:;base64,=\">") .append(content)//将页面内容写入 .append("</body></html>") .append(""); outputStream.write(httpResponse.toString().getBytes());//将文本转换为字节码 outputStream.close(); } } |
Servlet请求处理基类:FirstServlet.java
|
package org.mrzhangxd.com; /** * * @author mrzhangxd * */ public abstract class FirstServlet { public void servlet(FirstRequest firstRequest,FirstResponse firstResponse){ if(firstRequest.getMethod().equalsIgnoreCase("POST")){ doPost(firstRequest,firstResponse); }else if(firstRequest.getMethod().equalsIgnoreCase("GET")){ doGet(firstRequest,firstResponse); } } private void doGet(FirstRequest firstRequest, FirstResponse firstResponse) { // TODO Auto-generated method stub } private void doPost(FirstRequest firstRequest, FirstResponse firstResponse) { // TODO Auto-generated method stub } public void service(FirstRequest firstRequest, FirstResponse firstResponse) { // TODO Auto-generated method stub } } |
下一步servlet配置:FirstServletMapping.java
|
package org.mrzhangxd.com;
/** * * @author mrzhangxd * */ public class FirstServletMapping { private String servletName; private String url; private String clazz;
public FirstServletMapping(String servletName, String url, String clazz) { super(); this.servletName = servletName; this.url = url; this.clazz = clazz; }
public String getServletName() { return servletName; }
public void setServeletName(String servletName) { this.servletName = servletName; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getClazz() { return clazz; }
public void setClazz(String clazz) { this.clazz = clazz; } } |
其他配置:FirstServletMappingConfig.java
|
package org.mrzhangxd.com; import java.util.ArrayList; import java.util.List; /** * * @author mrzhangxd * */ public class FirstServletMappingConfig { public static List<FirstServletMapping> servletMappingList = new ArrayList<>(); static { servletMappingList.add(new FirstServletMapping("index", "/index", "firstTomcat.test.IndexServlet")); servletMappingList.add(new FirstServletMapping("firstblog", "/firstblog", "firstTomcat.test.MyBlog")); } } |
核心处理类:FirstTomcat.java,处理流程如下:
1) 提供Socket服务
2) 封装请求/响应对象
3) 将不同的请求映射到具体的Servlet处理
这里重点说的是,要利用 ServerSocket 通过服务器上的端口通信 以及 accpt方法一直等待客户端的请求
|
package org.mrzhangxd.com; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; /** * * @author mrzhangxd * */ public class FirstTomcat { private Integer port = 8080; //定义8080端口 private Map<String, String> urlServletMapping = new HashMap<>(); //存储url和对应的类 public FirstTomcat(Integer port) { super(); this.port = port; } @SuppressWarnings("resource") public void start() { initServletMapping(); try { ServerSocket serverSocket = null; //实例化一个 ServerSocket 对象,表示通过服务器上的端口通信 serverSocket = new ServerSocket(port); System.out.println("MyTomcat is starting..."); while(true) { Socket socket = serverSocket.accept(); //服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口 InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); FirstRequest myRequest = new FirstRequest(inputStream); FirstResponse myResponse = new FirstResponse (outputStream); dispatch(myRequest, myResponse); socket.close(); } }catch(Exception e) { e.printStackTrace(); } } //初始化映射 public void initServletMapping() { for(FirstServletMapping servletMapping : FirstServletMappingConfig.servletMappingList) { urlServletMapping.put(servletMapping.getUrl(), servletMapping.getClazz()); } } //分发请求 @SuppressWarnings("unchecked") public void dispatch(FirstRequest firstRequest, FirstResponse firstResponse) { String clazz = urlServletMapping.get(firstRequest.getUrl()); try { Class<FirstServlet> firstServletClass = (Class<FirstServlet>)Class.forName(clazz); FirstServlet firstservlet = firstServletClass.newInstance(); firstservlet.service(firstRequest, firstResponse); }catch(ClassNotFoundException e) { e.printStackTrace(); }catch(InstantiationException e) { e.printStackTrace(); }catch(IllegalAccessException e) { e.printStackTrace(); } } public static void main(String[] args) { FirstTomcat myTomcat = new FirstTomcat(8080); myTomcat.start(); } } |
测试类按照上面类里的注释自己解决,测试结果略。
注:
编码格式、注释都参考《代码整洁之道》
学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat的更多相关文章
- Tomcat与Servlet工作流程
什么是Tomcat? Tomcatserver是一个免费的开放源码的Web 应用server,属于轻量级应用server. 什么是Servlet? Servlet是在server上执行的小程序.,说白 ...
- Redux学习之我对于其工作流程的理解和实践
目录 1 工作流程图 2 各部位职责 3 Demo 1 工作流程图 2 各部位职责 我在理解这个流程图的时候,采用的是一种容易记住的办法,并且贴切实际工作职责. 我们可以把整个Redux工 ...
- spring+hibernate工作流程文件名理解
reg.jsp regsuccess.jsp User.java UserDAO.java UserDAOImpl.java User.hbm.xml Reg.java RegImpl.java Re ...
- 【Git项目管理】分布式 Git - 分布式工作流程
分布式 Git - 分布式工作流程 你现在拥有了一个远程 Git 版本库,能为所有开发者共享代码提供服务,在一个本地工作流程下,你也已经熟悉了基本 Git 命令.你现在可以学习如何利用 Git 提供的 ...
- =面试题:java面试基本方向 背1 有用 项目二技术学完再看
一.Java基础 1. 集合框架A)集合中泛型优点? 将运行期的ClaasCastException 转到编译期异常. 泛型还提供通配符 1)HashMap---允许一个键为null,允许多个值为n ...
- 零基础学完Python的7大就业方向,哪个赚钱多?
“ 我想学 Python,但是学完 Python 后都能干啥 ?” “ 现在学 Python,哪个方向最简单?哪个方向最吃香 ?” “ …… ” 相信不少 Python 的初学者,都会遇到上面的这些问 ...
- Tomcat内部结构、工作原理、工作模式和运行模式
TOMCAT的内部结构 Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的是Catalina servlet容器,其他组件按照一定的格式要求配置在这个顶层容器中.Tomcat的 ...
- 手动实现简单的tomcat服务器
手动实现tomcat服务器的流程: 分析具体的实现步骤: 1,浏览器和后端服务如何实现通信,首先传输的数据要遵循http协议,通过tcp也就是我们常说的套接字编程来实现,具体的底层数据传输肯定就是我们 ...
- 【Tomcat】Servlet 工作原理解析
Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.因而掌握 Servlet 的工作原理是成为一名合格的 Java Web 技术开发人员的 ...
随机推荐
- 奇妙的算法【9】YC每个小孩的糖果数,找公约数,最少硬币数
1,每个小孩的糖果数量是多少 有p个小孩,c个糖果,刚开始第1个小孩发一个糖果,第2个小孩发两个糖果,第p个小孩发p个糖果,如果糖果没有发完,就接着[注意]第1个小孩发p+1个糖果.....第p个小孩 ...
- 编程模型&编程思想
编程模型 1.面向对象编程OOP 2.面向切面编程AOP Java静态接口,Java动态代理,字节码提升. 面向切面的两个方面: 拦截判断:方法,注解,参数,异常 拦截执行:前置,后置,返回,异常 3 ...
- For... in 及 For… of 及 forEach
For... in 及 For… of let arr = ["a","b"]; for (let a in arr) { console.log(a) // ...
- 关于js异步的一些知识点
1,什么是单线程,和异步有什么关系 单线程-只有一个线程,只能做一件事 单线程的原因:避免DOM 渲染的冲突 浏览器需要渲染DOM JS 可以修改DOM 结构 JS 执行的时候,浏览器DOM 渲染会暂 ...
- MySQL: Can’t connect to MySQL server on (111 “Connection refused”)
1. Mysql连接问题 远程访问mysql或者通过docker访问宿主机mysql经常会碰到下面的问题: Can't connect to MySQL server on (111 "Co ...
- vue嵌套数据多层级里面的数据不自动更新渲染dom
可以尝试手动调用更新 主要代码: vm.$forceUpdate() 官网
- Docker部署code-server
Docker部署code-server 版本:codercom/code-server:v2 code-server可以放在服务器上,随时随地在浏览器中,编写代码.运行.调试: 手机,pad都可以进行 ...
- 用js刷剑指offer(二进制中一的个数)
题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 牛客网链接 思路 如果一个整数不为0,那么这个整数至少有一位是1.如果我们把这个整数减1,那么原来处在整数最右边的1就会变为 ...
- Python基础之While循环
一.摘要 本片博文将介绍input()函数和while循环的使用 二.input()函数 函数input() 让程序暂停运行,等待用户输入一些文本.获取用户输入后,Python将其存储在一个变量中,以 ...
- PHP批量更新MYSQL中的数据
原文链接:https://blog.csdn.net/wuming19900801/article/details/62893429 $sql = "update newhouse_clic ...