点击查看代码
package com.grady.diytomcat;

import com.grady.diytomcat.handler.RequestHandler;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List; public class DiyTomcat { private int port = 8080; public static final HashMap<String, DiyServlet> SERVLET_MAPPING = new HashMap<>(); public static final HashMap<String,String> URL_MAPPING = new HashMap<>(); static {
loadServlet();
} private static void loadServlet() {
try {
//获取web.xml目录地址
String path = DiyTomcat.class.getResource("/").getPath();
SAXReader reader = new SAXReader();
//读取web.xml文件
Document document = reader.read(new File(path + "web.xml"));
//获取根标签(servlet和servlet-mapping),放在一个List中
Element rootElement = document.getRootElement();
List<Element> elements = rootElement.elements();
//循环将映射写进map映射里
for(Element element : elements){
if ("servlet".equalsIgnoreCase(element.getName())){
Element servletName = element.element("servlet-name");
Element servletClass = element.element("servlet-class");
//需要注意的是servletMapping映射的第二个参数,要通过反射的方式进行实例化
SERVLET_MAPPING.put(servletName.getText(),
(DiyServlet) Class.forName(servletClass.getText().trim()).newInstance());
}else if ("servlet-mapping".equalsIgnoreCase(element.getName())){
Element servletName = element.element("servlet-name");
Element urlPattern = element.element("url-pattern");
URL_MAPPING.put(urlPattern.getText(), servletName.getText());
}
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
} public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
Socket socket = serverSocket.accept();
RequestHandler requestHandler=new RequestHandler(socket);
// 一个 socket 一个线程
new Thread(requestHandler).start();
}
}
}
1. 根据tomcat的特性,首先是要有解析web.xml的能力

loadServlet方法即是通过dom4j的能力来解析web.xml,经其中的内容创建成对应的数据结构缓存到SERVLET_MAPPINGURL_MAPPING

待解析的web.xml的内容,由于是单元测试测试,所以在testresource目录下

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>com.grady.diytomcat.servlet.TestServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping> </web-app>
2. 由于第一个版本 是单线程的,所有第一个版本只能串行执行请求,这个版本改为每接收到一个请求就创建一条线程来处理请求中的内容
public void start() throws IOException {
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
Socket socket = serverSocket.accept();
RequestHandler requestHandler=new RequestHandler(socket);
// 一个 socket 一个线程
new Thread(requestHandler).start();
}
}

完整代码:

https://github.com/ZhongJinHacker/diy-tomcat/tree/bio-tomcat

手写tomcat——编写一个提供servlet能力的 http服务器的更多相关文章

  1. 手写tomcat——编写一个echo http服务器

    核心代码如下: public class DiyTomcat1 { public void run() throws IOException { ServerSocket serverSocket = ...

  2. 手写tomcat——有线程池化能力的servlet 服务

    点击查看代码 public class DiyTomcat { private int port = 8080; public static final HashMap<String, DiyS ...

  3. 手写tomcat——概述

    1. 使用java 编写一个echo http服务器 使用java 编写一个echo http服务器 https://github.com/ZhongJinHacker/diy-tomcat/tree ...

  4. 手写Tomcat

    学习JavaWeb之后,只知道如何部署项目到Tomcat中,而并不了解其内部如何运行,底层原理为何,因此写下此篇博客初步探究一下.学习之前需要知识铺垫已列出:Tomcat目录结构.HTTP协议.IO. ...

  5. 手写Tomcat服务器

    预备知识 编写服务器用到的知识点 1) Socket 编程2) HTML3) HTTP 协议4) 反射5) XML 解析6) 服务器编写 Socket编程 https://www.cnblogs.co ...

  6. 编写一个小Servlet程序

    1.编写一个java类,此类继承HttpServlet 创建完工程(见上一篇随笔:使用eclipse创建在myeclipse中运行的web工程),在src中新建一个包,包名字叫servlet:再新建一 ...

  7. 利用sklearn对MNIST手写数据集开始一个简单的二分类判别器项目(在这个过程中学习关于模型性能的评价指标,如accuracy,precision,recall,混淆矩阵)

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...

  8. 手写系列-实现一个铂金段位的 React

    一.前言 本文基于 https://pomb.us/build-your-own-react/ 实现简单版 React. 本文学习思路来自 卡颂-b站-React源码,你在第几层. 模拟的版本为 Re ...

  9. Python网络编程——编写一个简单的回显客户端/服务器应用

    今天将python中socket模块的基本API学习完后,照着书上的实例编写一个套接字服务器和客户端.采用python3.5版本,在注释中会标明python2和python3的不同之处. 1.代码 ( ...

随机推荐

  1. 从位图到布隆过滤器,C#实现

    前言 本文将以 C# 语言来实现一个简单的布隆过滤器,为简化说明,设计得很简单,仅供学习使用. 感谢@时总百忙之中的指导. 布隆过滤器简介 布隆过滤器(Bloom filter)是一种特殊的 Hash ...

  2. MySQL进行 批量插入,批量删除,批量更新,批量查询

    1.批量插入 ServiceImpl层 List<Person> addPeople = new ArrayList<>(); //addPeople存放多个Person对象 ...

  3. NC202498 货物种类

    NC202498 货物种类 题目 题目描述 某电商平台有 \(n\) 个仓库,编号从 \(1\) 到 \(n\) . 当购进某种货物的时候,商家会把货物分散的放在编号相邻的几个仓库中. 我们暂时不考虑 ...

  4. HMS Core 机器学习服务打造同传翻译新“声”态,AI让国际交流更顺畅

    2022年6月,HMS Core机器学习服务面向开发者提供一项全新的开放能力--同声传译,通过AI语音技术减少资源成本,加强沟通交流,旨在帮助开发者制作丰富多样的同声传译应用. HMS Core同声传 ...

  5. 万字干货|Java基础面试题(2022版)

    目录 概念常识 Java 语言有哪些特点? JVM.JRE和JDK的关系 什么是字节码? 为什么说 Java 语言是"编译与解释并存"? Oracle JDK 和OpenJDK的区 ...

  6. 前端学做 PPT

    前端学做 PPT 公司做技术分享.年终总结都需要用到ppt. 要快速.省事的做出高质量的 ppt,一方面需要熟练使用制作 ppt 的工具,另一方面得知道用工具做成什么样子才是好作品.前者比较简单,后者 ...

  7. IDEA快捷键-03

    用了很久的eclipse,换了新的公司,跟着团队的习惯也转到idea上来了.在这里记录下对idea的认识,常用的idea快捷键及使用技巧. 对比eclipse每个workspace打开一个窗口,ide ...

  8. Java的学习日常

    当2020年10月进入大学,我选择了计算机专业,本想着自己会摒弃高中的不良习惯,认真学习.但随着和同学们的熟悉,自己的本性也逐渐暴露出来.两年懒散表现,让现在回过头的自己都不忍直视. 虽然在学习期间, ...

  9. typescript中的esModuleInterop选项

    当没有加esModuleInterop时 库的代码: export const a = 1; export default function b() {} 生成代码 exports.__esModul ...

  10. HashSet集合的介绍和哈希值

    java.util.Set接口 extends Collection接口 Set接口的特点: 1.不允许存储重复的元素 2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历 java.uti ...