二.手写迷你版Tomcat-minicat2.0

2023-05-16

minicat 1.0我们实现了返回固定的字符串"Hello minicat"。
minicat 2.0需求:
封装Request和Response对象,返回html静态资源文件。

封装Request对象

想要封装Request对象,得要先知道请求信息里面有哪些数据,所以我们先打印请求信息。

/**
     * minicat启动需要初始化展开的一些操作
     */
    public void start() throws IOException {
        // 监听端口
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("---->>>minicat start on port:"+port);

        //minicat 1.0
//        while (true) {
//            String data = "Hello minicat!";
//            Socket socket = serverSocket.accept();
//            // 有了socket,接收到请求,获取输出流
//            OutputStream outputStream = socket.getOutputStream();
//            String responseText = HttpProtocolUtil.getHttpHeader200(data.getBytes().length)+data;
//            outputStream.write(responseText.getBytes());
//            socket.close();
//        }

        // minicat 2.0
        while (true) {
            Socket socket = serverSocket.accept();
            // 获取输入流
            InputStream inputStream = socket.getInputStream();
            // 因为网络请求会有间断性,所以需要确认数据流必须存在
            int count = 0;
            while (count == 0) {
                // 从输入流中获取请求信息
                count = inputStream.available();
            }

            byte[] bytes = new byte[count];
            // 读取数组
            inputStream.read(bytes);
            System.out.println("====>>> 请求信息:"+new String(bytes));

            socket.close();
        }
    }

打印信息如下:

====>>> 请求信息:GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7

根据打印出来的请求信息,找到重点要封装的地方 “GET / HTTP/1.1” 。

  • “GET”请求方式需要封装,因为后面会根据不同的请求方式找不同的servlet。
  • GET后面的“/”也需要封装,这代表的是请求路径。
  • “HTTP/1.1”这里不需要要封装,tomcat默认就用HTTP/1.1。

定义Request对象
经过分析,我们需要封装请求方式和请求路径,所以Request定义如下:

/**
 * 把请求信息封装成Request对象(根据inputStream输入流封装)
 */
public class Request {
    // 请求方式,GET/POST
    private String method;
    // 请求路径,例如:/,/index.html
    private String url;

    // 输入流,其他属性从输入流中解析出来
    private InputStream inputStream;
    
	// getter setter...
}

在Request实体中增加构造方法,给method和url赋值

public Request() {
    }

public Request(InputStream inputStream) throws IOException {
     this.inputStream = inputStream;

     // 因为网络请求会有间断性,所以需要确认数据流必须存在
     int count = 0;
     while (count == 0) {
         // 从输入流中获取请求信息
         count = inputStream.available();
     }

     byte[] bytes = new byte[count];
     // 读取数组
     inputStream.read(bytes);
     // 转换成String
     String inputStr = new String(bytes);

     //获取第一行请求信息
     String firstLineStr = inputStr.split("\\n")[0]; // GET / HTTP/1.1
     String[] strings = firstLineStr.split(" ");
     // 请求方式
     this.method = strings[0];
     // 请求路径
     this.url = strings[1];
 }

封装Response对象

Response对象中需要做的事情,根据url获取静态资源绝对路径,进一步根据绝对路径获取静态资源,最终通过输出流输出
获取静态资源文件的绝对路径

public class StaticResourceUtil {
	 public static String getAbsolutePath(String path) {
	     // 获取绝对路径
	     String absolutePath = StaticResourceUtil.class.getResource("/").getPath();
	     return absolutePath.replaceAll("\\\\","/")+path;
	 }
}

根据绝对路径获取静态资源

        File file = new File(absoluteResourcePath);

通过输出流输出

public class StaticResourceUtil {
	 public static void outputStaticResource(InputStream inputStream, OutputStream outputStream) throws IOException {
        int count = 0;
        while (count == 0) {
            count = inputStream.available();
        }

        int resourceSize = count;
        // 输出http请求头
        outputStream.write(HttpProtocolUtil.getHttpHeader200(resourceSize).getBytes());
        // 读取内容
        long written = 0; // 已经读取的内容长度
        int byteSize = 1024; // 计划每次缓冲的长度
        byte[] bytes = new byte[byteSize];

        // 输出具体内容
        // 循环读取,直到读取完
        while (written < resourceSize) {
            if (written + byteSize > resourceSize) { // 说明剩余未读取大小不足一个1024长度,那就按真实长度处理
                // 剩余的文件长度
                byteSize = (int) (resourceSize - written);
                bytes = new byte[byteSize];
            }

            inputStream.read(bytes);
            outputStream.write(bytes);

            written+=byteSize;
        }
    }
}

Response完整代码如下:

/**
 * 封装Response对象,需要依赖于OutputStream
 *
 * 该对象需要提供核心方法,输出html
 */
public class Response {

    private OutputStream outputStream;

    public Response() {
    }

    public Response(OutputStream outputStream) {
        this.outputStream = outputStream;
    }

    /**
     * 使用输出流输出指定字符串
     * @param content
     * @throws IOException
     */
    public void output (String content) throws IOException {
        outputStream.write(content.getBytes());
    }

    /**
     * 根据url获取静态资源绝对路径,进一步根据绝对路径获取静态资源,最终通过输出流输出
     * @param path
     */
    public void outputHtml(String path) throws IOException {
        // 获取静态资源绝对路径
        String absoluteResourcePath = StaticResourceUtil.getAbsolutePath(path);

        // 输出静态资源文件
        File file = new File(absoluteResourcePath);
        if (file.exists() && file.isFile()) {
            // 读取静态资源文件,输出静态资源
            StaticResourceUtil.outputStaticResource(new FileInputStream(file),outputStream);
        }else{
            // 输出404
            output(HttpProtocolUtil.getHttpHeader404());
        }
    }
}

V2.0测试

启动类中更改如下

/**
     * minicat启动需要初始化展开的一些操作
     */
    public void start() throws IOException {
        // 监听端口
        ServerSocket serverSocket = new ServerSocket(port);
        System.out.println("---->>>minicat start on port:"+port);

        //minicat 1.0
//        while (true) {
//            String data = "Hello minicat!";
//            Socket socket = serverSocket.accept();
//            // 有了socket,接收到请求,获取输出流
//            OutputStream outputStream = socket.getOutputStream();
//            String responseText = HttpProtocolUtil.getHttpHeader200(data.getBytes().length)+data;
//            outputStream.write(responseText.getBytes());
//            socket.close();
//        }

        // minicat 2.0
        while (true) {
            Socket socket = serverSocket.accept();
            // 获取输入流
            InputStream inputStream = socket.getInputStream();

            //封装Request和Response
            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());

            response.outputHtml(request.getUrl());
            socket.close();

        }
    }

	/**
     * minicat 的程序启动入口
     * @param args
     */
    public static void main(String[] args) {
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

在resources目录下增加index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>静态资源</title>
</head>
<body>
Hello minicat 静态资源
</body>
</html>

启动效果如下:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二.手写迷你版Tomcat-minicat2.0 的相关文章

随机推荐

  • 立即数

    一 概念 xff1a 通常把在 立即寻址方式 指令中给出的数称为立即数 二 判断步骤 xff1a 把数据转换成二进制 xff0c 从低到高写成 4 个一组 xff0c 最高位不够一组的补 0 xff1b 数 1 的个数 xff0c 如果大于
  • 位、字节、char、int(32位系统) 之间的关系

    一 概念 xff1a 位 xff08 bit xff09 xff1a 计算机中最小的数据单位 每一位的状态只能是0或1 字节 xff08 byte xff09 xff1a 存储空间的基本计量单位 xff0c 8 个二进制位构成1个字节 1
  • C语言中的那些宏

    DATE 进行预处理的日期 xff08 Mmm dd yyyy 形式的字符串文字 xff09 FILE 代表当前源代码文件名的字符串文字 LINE 代表当前源代码中的行号的整数常量 TIME 源文件编译时间 xff0c 格式微 hh xff
  • 任务栈简单入门

    最近又把两本进阶书看了一遍 xff0c 但总感觉好记性不如烂笔头 xff0c 所以还是决定通过博客记录一下 xff0c 我们将分两篇来全面深入地记录Activity 启动模式与任务栈的内容 android任务栈简单了解 1 android任
  • VS2010里函数枚举

    一 cout函数 说明 xff1a 调用该函数必须申明头文件 include lt iostream gt 同时声明后面必须使用 using namespace std 正确书写为 xff1a include lt iostream gt
  • I_O—标准 I_O 实验

    一 测试标准 I O 一次可以同时打开多少个文件 1 实验思路 xff1a 利用循环同时打开文件 xff0c 直到不能打开 2 代码如下 xff1a 二 fgetc 和 fputc 实现拷贝文件并输出文件行数 1 实验思路 xff1a 打开
  • Source Insight 配色方案

    Source Insight 对于程序员来说应该不陌生 xff0c 当然一个个性化的编程界面也会让自己赏析悦目 xff0c 下面就将个人的界面设置分享一下 xff1a 一 背景色设置 1 选择 Options Preferences 2 选
  • Linux 网络——交换机不能用两根网线相连

    同一个局域网所有的交换机之间可以用网线串联起来 xff0c 但绝对不能使任意 gt 61 2个交换机形成环路 xff0c 否则局域网内将形成广播风暴 xff0c 所用局域网内的用户都将不能上网 例如局域网内的交换机可以使用如下相连 xff1
  • GDB 知识点——基础操作

    Linux C 中的 GDB 调试使用 xff1a 1 GDB 的主要功能 xff1a 1 启动被调试程序 2 让被调试的程序在指定的位置停住 3 当程序被停住时 xff0c 可以检查程序状态 xff08 如变量的值 xff09 2 检查
  • 员工管理系统(C 语言)——项目说明

    项目名称 xff1a 员工管理系统 项目目的 xff1a 1 实现简单的公司对员工信息的管理 2 通过项目锻炼实现逻辑转换为代码的能力 3 利用函数封装实现项目过程中的逻辑过程以及需求功能的实现 4 学会数据库的操作以及网络通信 5 强化代
  • 员工管理系统(C 语言)——客户端解析

    源码下载地址 xff1a https download csdn net download wenfei11471 10477504 客户端功能 xff1a 1 运行时先测试是否能连通服务器 xff08 不畅通如下图所示 xff09 xff
  • 员工管理系统(C 语言)——服务器解析

    源码下载地址 xff1a https download csdn net download wenfei11471 10477504 服务器功能 xff1a 1 运行时主界面 xff08 服务器启动后 xff0c 只有管理员下线 xff0c
  • 排序——选择排序、冒泡排序和快速排序比较

    一 选择排序思路 xff1a 1 以 int 类型为例 2 拿第一个数与后面数相比较 xff0c 如果比后面的数大则交换 3 拿第二个数与后面的数比较 xff0c 如果比后面的数大则交换 4 直到比较到倒数第二个数 xff0c 最后一个数不
  • C 语言中 const 与指针的结合使用

    请区分一下几种指针的区别 1 const int p 2 int const p 3 int const p 4 const int const p 5 const int const p 解析 xff1a 1 const int p 中
  • Ubuntu16.04上安装百度网盘后打不开

    现在百度网盘推出了Linux版本 xff0c 也有Ubuntu下安装的deb文件 xff0c 但是我在Ubuntu上安装后却打不开 xff0c 报错 baidunetdisk crashed with SIGABRT in gnu cxx
  • C/C++的“文件包含”处理时头文件被重复包含的问题探究及解决方法(用最简单的例子进行说明)

    这篇博文是博文https blog csdn net wenhao ir article details 125668051的配套博文 头文件被重复包含是下面这样的现象 xff1a A文件里包含了C文件 xff0c B文件里也包含了C文件
  • BIN,BCD,ASCII码分别对应的Hex(16进制)数

    BIN BCD ASCII码分别对应的Hex xff08 16进制 xff09 数 以十进制的 56 为例 BIN 码 对应二进制数为 0011 1000对应Hex数据为 0x38BIN码就是二进制数 xff1b 压缩BCD 码 对应二进制
  • .LDS 文件详解

    最近在研究uboot xff0c 红色部分为我加上的注解 转载地址 xff1a http blog chinaunix net space php uid 61 23373524 amp do 61 blog amp cuid 61 232
  • 13 select的优化一

    1 上个例子中 xff0c select通过for循环轮询client套接字 xff0c 轮询的范围比较大 xff0c 有优化的地方 2 优化代码 xff1a 通过数组存储client的套接字 xff0c 达到少轮询的效果 xff0c 可以
  • 二.手写迷你版Tomcat-minicat2.0

    minicat 1 0我们实现了返回固定的字符串 34 Hello minicat 34 minicat 2 0需求 xff1a 封装Request和Response对象 xff0c 返回html静态资源文件 封装Request对象 想要封