Hello大家好,本章我们自己实现一个简易版的tomcat 。有问题可以联系我mr_beany@163.com。另求各路大神指点,感谢

程序的运行少不了服务器的支持,而tomcat因其性能稳定,免费等优点,深受 Java 爱好者的喜爱并得到了部分软件开发商的认可,为目前比较流行的 Web 应用服务器。

那么到底它是怎么运行的呢?今天我们来实现一个简化版tomcat来感受一下。

一:导入解析xml的jar包

<dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version>
</dependency>复制代码

二:编写XML解析类

package com.example.demo.utils;import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;/*** @author zy*/
public class XmlUtils {/*** 定义解析器和文档对象*/public SAXReader saxReader;public Document document;public XmlUtils(String path) {//获取解析器saxReader = new SAXReader();try {//获取文档对象document = saxReader.read(path);} catch (DocumentException e) {e.printStackTrace();}}/*** 获取节点下的所有节点** @param name* @return*/public List<Element> getNodes(String name) {Element root = document.getRootElement();return root.elements(name);}
}
复制代码

三:实现Request和Response

其中Request是对浏览器的请求的封装,而Response是对浏览器请求的响应,换而言之就是Request 用来取出请求信息,而 Response 则用来添加要返回给浏览器的信息。

创建Request.java

package com.example.demo.http;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;/*** @author zy*/
public class Request {private String method;private String url;public Request(InputStream inputStream) throws IOException {BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));String[] methodAndUrl = bufferedReader.readLine().split(" ");this.method = methodAndUrl[0];this.url = methodAndUrl[1];System.out.println("请求类型:"+ method);System.out.println("请求路径:"+ 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;}}复制代码

创建Response.java

package com.example.demo.http;import java.io.OutputStream;/*** @author zy*/
public class Response {private OutputStream outputStream;private String write;public Response(OutputStream outputStream){this.outputStream = outputStream;}public String getWrite() {return write;}public void setWrite(String write) {this.write = write;}}复制代码

四:实现Servlet

先做个接口

package com.example.demo.servlet;import com.example.demo.http.Request;
import com.example.demo.http.Response;/*** @author zy*/
public abstract class AbstractServlet {public abstract void doGet(Request request, Response response);public abstract void doPost(Request request, Response response);
}复制代码

再来实现自己的Servlet

package com.example.demo.servlet;import com.example.demo.http.Request;
import com.example.demo.http.Response;/*** @author zy*/
public class FirstServlet extends AbstractServlet {@Overridepublic void doGet(Request request, Response response) {response.setWrite("我的第一个Servlet");}@Overridepublic void doPost(Request request, Response response) {this.doGet(request, response);}
}复制代码

五:创建web.xml

这里配置了请求路径的servlet的对应关系,文件放在resources文件夹下

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"><servlet><servlet-name>first.html</servlet-name><servlet-class>com.example.demo.servlet.FirstServlet</servlet-class></servlet><servlet-mapping><servlet-name>first.html</servlet-name><url-pattern>/first.html</url-pattern></servlet-mapping></web-app>复制代码

六,创建tomcat,初始化配置文件

package com.example.demo.tomcat;import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;import com.example.demo.utils.XmlUtils;
import org.dom4j.Element;/*** @author zy*/
public class Tomcat {/*** 设置端口号*/private static final int PORT = 8080;public static final HashMap<String, Object> SERVLET_MAPPING = new HashMap<>();public static final HashMap<String, Object> SERVLET = new HashMap<>();/*** 控制服务器启动关闭*/public boolean tomcatStarBool = true;private void init() {InputStream io = null;try {System.out.println("加载配置文件开始");//读取配置文件XmlUtils xml = new XmlUtils(XmlUtils.class.getResource("/")+"web.xml");//将所有的类都存储到容器中List<Element> list = xml.getNodes("servlet");for (Element element : list) {SERVLET.put(element.element("servlet-name").getText(),Class.forName(element.element("servlet-class").getText()).newInstance());}//映射关系创建List<Element> list2 = xml.getNodes("servlet-mapping");for (Element element : list2) {SERVLET_MAPPING.put(element.element("url-pattern").getText(),element.element("servlet-name").getText());}System.out.println("加载配置文件结束");} catch (Exception ex) {ex.printStackTrace();} finally {if (io != null) {try {io.close();} catch (Exception e) {e.printStackTrace();}}}}}复制代码

七:创建处理请求任务的SocketProcess

package com.example.demo.tomcat;import com.example.demo.http.Request;
import com.example.demo.http.Response;
import com.example.demo.servlet.AbstractServlet;import java.io.OutputStream;
import java.net.Socket;/*** @author zy*/
public class SocketProcess extends Thread{protected Socket socket;public SocketProcess(Socket socket){this.socket = socket;}@Overridepublic void run() {try {Request request = new Request(socket.getInputStream());Response response = new Response(socket.getOutputStream());String servletName = (String) Tomcat.SERVLET_MAPPING.get(request.getUrl());if(servletName!=null && !servletName.isEmpty()) {//映射有的话找到对应的对象AbstractServlet servlet = (AbstractServlet) Tomcat.SERVLET.get(servletName);if(servlet!=null) {servlet.doGet(request, response);}else {System.out.println("找不到对应的servlet");}}else {System.out.println("找不到对应的servletMapping");}String res = response.getWrite();OutputStream outputStream = socket.getOutputStream();outputStream.write(res.getBytes("GBK"));outputStream.flush();outputStream.close();}catch (Exception ex){ex.printStackTrace();}finally {if (socket != null) {try {socket.close();} catch (Exception e) {e.printStackTrace();}}}}
}复制代码

八:在tomcat.java中添加启动方法

private void start() {try {ServerSocket serverSocket = new ServerSocket(PORT);System.out.println("Tomcat 服务已启动,地址:localhost ,端口:" + PORT);this.init();//持续监听do {Socket socket = serverSocket.accept();//处理任务Thread thread = new SocketProcess(socket);thread.start();} while (tomcatStarBool);} catch (IOException e) {e.printStackTrace();}
}public static void main(String[] args) {Tomcat tomcat = new Tomcat();tomcat.start();
}复制代码

九:测试

启动在tomcat.java中运行void main方法

出现如下字样代表启动成功,然后地址栏中输入

http://localhost:8080/first.html

?????为什么是这样。。。。。。

啊!原来没有添加响应头信息

Response.java中加入

/*** 响应头信息*/
public static final String RESPONSE_HEADER ="HTTP/1.1 200 \r\n"+ "Content-Type: text/html\r\n"+ "\r\n";复制代码

SocketProcess.java中

String res = response.getWrite();复制代码

改成

String res = Response.RESPONSE_HEADER + response.getWrite();复制代码

重新启动,访问

结尾

祝大家新年快乐。感谢支持!

其他文章:

从零搭建自己的springboot后台框架

码云地址: gitee.com/beany/mySpr…

GitHub地址: github.com/MyBeany/myS…

从零手动实现简易Tomcat相关推荐

  1. Android 从零开发一个简易的相机App

    本文介绍了实现一个简易Android相机App过程中,遇到的一些问题,对Camera API的选型.通知相册更新.跳转相册.左右滑动界面切换拍照/录像,相机切换时候的高斯模糊虚化效果.相机切换的3D效 ...

  2. 从零实现 SpringBoot 简易读写分离,也不难嘛!

    作者 | 温安适 来源 | https://my.oschina.net/floor/blog/1632565 最近在学习Spring boot,写了个读写分离.并未照搬网文,而是独立思考后的成果,写 ...

  3. 从零实现一个简易jQuery框架之一—jQuery框架概述

    我们知道,不管学习任何一门框架,了解其设计的理念.目的.总体的结构及核心特性对我们使用和后续的深入理解框架都是有很大的帮助的.因此在这里先梳理一下本人对jQuery框架的一些理解. 设计目的(为什么要 ...

  4. 从零实现SpringBoot简易读写分离,也不难嘛!

    作者:温安适 my.oschina.net/floor/blog/1632565 最近在学习Spring boot,写了个读写分离.并未照搬网文,而是独立思考后的成果,写完以后发现从零开始写读写分离并 ...

  5. 【零基础】简易价差K线合成方法介绍

    交流Q群1064240775 一.前言 价差K线合成一直是某种"高端"的应用,因为做套利交易的本来就少,做自设套利的就更少了.目前市面上支持套利且比较成熟的终端有极星和文华,极星支 ...

  6. Tomcat优化总结

    一.配置tomcat管理员账户 在conf/ tomcat-users.xml下添加用户: <user username="admin" password="123 ...

  7. Tomcat性能优化

    1.  目的 通过优化tomcat提高网站的并发能力.当我们今天我们将这个优化讲完之前  优化完成后看能达到什么层次. 2.  服务器资源 服务器所能提供CPU.内存.硬盘的性能对处理能力有决定性影响 ...

  8. linux定时重启tomcat的脚本,linux定时重启tomcat服务的脚本学习

    要求:在linux中定时重启一个tomcat服务 一:shell脚本即Shell Script [1],Shell脚本与Windows/Dos下的批处理相似,也就是用各类命令预先放入到一个文件中,方便 ...

  9. java打包后发布找不到jsp_eclipse中web项目部署以后jsp的java文件找不到问题(Tomcat配置serverlocations)...

    我的开发环境:eclipse kepler (4.3)+tomcat7.0.42. 在我想看eclipse中web项目jsp文件被tomcat转换成java以后的java源文件的位置,发现正常情况下的 ...

最新文章

  1. 使用Nucleus SE实时操作系统
  2. 插入排序 链表 java_Java实现 LeetCode 147 对链表进行插入排序
  3. 【Flutter】顶部导航栏实现 ( Scaffold | DefaultTabController | TabBar | Tab | TabBarView )
  4. Oracle 11g RAC 第二节点root.sh执行失败后再次执行root.sh
  5. BZOJ2809 dispatching 【可并堆】
  6. 添加蜂窝注册表及永久存储
  7. 在计算机网络中发送电子邮件遵循的协议是,一、计算机网络刷题
  8. 宇轩网络面试题目PHP,二十道接地气的php面试题,让你直接通过面试!就此奉上~...
  9. DataGrip使用入门
  10. 这个容器逃逸 exploit 获得首届年度谷歌云平台大奖10万美元
  11. 【NOIP-2017PJ】图书管理员
  12. python 通达信k线_通达信自定义数据采集,使用python在通达信里面选股
  13. 2022年成都初级审计师考试测试题及答案
  14. 苏轼一生最智慧的20首诗词,不读懂不足以谈人生
  15. 怎样通过计算机修改蓝牙音箱,有线音箱怎么改蓝牙无线音箱 有线音箱改无线音箱方法介绍【详解】...
  16. php太平洋时间转成北京时间,北京时间 → 太平洋时间 换算表 和太平洋时间 → 北京时间 换算表...
  17. (MATLAB)大家来找茬-简易的彩色图像找不同
  18. vue移动端点击事件延迟_如何解决移动端Click事件300ms延迟的问题?
  19. 本地文件共享到云服务器,本地文件共享到云服务器
  20. python逐行读取数据_python – Pandas按行读取数据

热门文章

  1. 计算机中文件访问时间是什么情况,【反计算机取证必看】Windows系统中文件时间属性的变化及影响因素.pdf...
  2. QT每日一练day29:QT中的多线程探究
  3. #自定义多级菜单_怎么搞定排版中的多级列表问题?
  4. mysql忘记密码找回密码_MySQL忘记密码找回 重置MySQL root用户密码
  5. spark 读取多个路径_spark
  6. C语言do while语句
  7. 编程完数_初级编程C++题:11H1343: 完数
  8. python3 copy_Python3 深浅拷贝
  9. java判断 图片_java判断是否为图片的步骤和方法
  10. matplotlib 直方图_掌握了Matplotlib这两个方法,轻松绘制出漂亮的直方图!