手写一个民用Tomcat (02)

01 我们已经完成了 基本玩具一样的Tomcat,可以实现这个功能,下面我们在规范一下

先从我们的JxdResponse ,JxdRequest  分别实现ServletRequest ,和ServletResponse

注意下 没有用的到 重写方法我就 直接去掉了,你自己可以在代码中实现以下


public class JxdResponse implements ServletResponse{
    private static final int BUFFER_SIZE = 1024;
    JxdRequest request;

    OutputStream output;
    PrintWriter writer;
    String contentType = null;
    long contentLength = -1;
    String charset = null;
    String characterEncoding = null;

    public OutputStream getOutput() {
        return output;
    }

    public void setOutput(OutputStream output) {
        this.output = output;
    }

    public JxdResponse(OutputStream output) {
        this.output = output;
    }

    public void setRequest(JxdRequest request) {
        this.request = request;
    }

    /**
     * 这个方法是静态方法演示
     * @throws IOException
     */
    public void sendStaticResource() throws IOException {
        byte[] bytes = new byte[BUFFER_SIZE];
        FileInputStream fis = null;
        try {
            File file = new File(JxdHttpServer.FILE_ROOT, request.getUri());
            if (file.exists()) {
                fis = new FileInputStream(file);
                int ch = fis.read(bytes, 0, BUFFER_SIZE);
                while (ch != -1) {
                    output.write(bytes, 0, ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                }
                output.flush();
            } else {
                String errorMessage = "HTTP/1.1 404 FIle Not Found\r\n" +
                        "Content-Type: text/html\r\n" +
                        "Content-Length: 23\r\n" +
                        "\r\n" +
                        "<h1>error未知</h1>";
                output.write(errorMessage.getBytes());
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            if(fis != null) {
                fis.close();
            }
        }
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        writer = new PrintWriter(new OutputStreamWriter(output,getCharacterEncoding()), true);
        return writer;
    }

    @Override
    public String getCharacterEncoding() {
        return characterEncoding;
    }

    @Override
    public void setCharacterEncoding(String characterEncoding) {
        this.characterEncoding = characterEncoding;
    }

    @O
}

import javax.servlet.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;

public class JxdRequest implements ServletRequest {
    private InputStream input;
    private String uri;

    public JxdRequest(InputStream input) {
        this.input = input;
    }

    public void parse() {
        StringBuffer request = new StringBuffer(2048);
        int i;
        byte[] buffer = new byte[2048];
        try {
            i = input.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
            i = -1;
        }
        for (int j = 0; j < i; j++) {
            request.append((char) buffer[j]);
        }
        uri = parseUri(request.toString());
    }

    private static String parseUri(String requestString) {

        int index1, index2;
        index1 = requestString.indexOf(' ');
        if (index1 != -1) {
             index2 = requestString.indexOf(' ', index1 + 1);
             if (index2 > index1) return requestString.substring(index1 + 1, index2);
        }
        return null;
    }

    public String getUri() {
        return uri;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return null;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return null;
    }
}

JxdHttpConnector  实现Runnable  接口 


import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class JxdHttpConnector implements Runnable {

    @Override
    public void run() {
        ServerSocket serverSocket = null;
        int port = 8080;
        try {
            serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        while (true) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();

                //交给HttpProcessor 处理
                JxdHttpProcessor processor = new JxdHttpProcessor();
                processor.process(socket);
                //交给HttpProcessor 完成 关闭
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void start() {
        Thread thread = new Thread(this);
        thread.start();
    }
}

JxdHttpProcessor  处理方法 没太大变化


import org.apache.commons.lang.text.StrSubstitutor;

import javax.servlet.Servlet;
import java.io.*;
import java.net.*;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

public class JxdHttpProcessor {

    public void process(Socket socket) { //服务器循环等待请求并处理
        while (true) {
            InputStream input = null;
            OutputStream output = null;
            try {
                input = socket.getInputStream();
                output = socket.getOutputStream();
                // create Request object and parse
                JxdRequest request = new JxdRequest(input);
                request.parse();
                // create Response object
                JxdResponse response = new JxdResponse(output);

                if (request.getUri().startsWith("/servlet/")) {
                    //加载动态资源
                    JxdServletProcessor jxdServletProcessor = new JxdServletProcessor();
                    jxdServletProcessor.process(request, response);
                } else {
                    //加载静态资源
                    StaticResourceProcessor staticResourceProcessor = new StaticResourceProcessor();
                    staticResourceProcessor.process(request, response);
                }
            } catch (Exception ea) {
                ea.printStackTrace();
            }
        }
    }
}


import org.apache.commons.lang.text.StrSubstitutor;

import javax.servlet.Servlet;
import java.io.*;
import java.net.*;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

public class JxdServletProcessor {
    //根据HTTP协议响应头定义,里面包含变量
    private static String OKMessage = "HTTP/1.1 ${StatusCode} ${StatusName}\r\n" +
            "Content-Type: ${ContentType}\r\n" +
            "Server: minit\r\n" +
            "Date: ${ZonedDateTime}\r\n" +
            "\r\n";

    public void process(JxdRequest request, JxdResponse response) {
//首先根据uri最后一个/号来定位,后面的字符串认为是servlet名字
        String uri = request.getUri();
        String servletName = uri.substring(uri.lastIndexOf("/") + 1);
        URLClassLoader loader = null;

        PrintWriter printWriter =null;
        try {
// create a URLClassLoader
            URL[] urls = new URL[1];
            URLStreamHandler streamHandler = null;
            File classPath = new File(JxdHttpServer.WEB_ROOT);
            String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
            urls[0] = new URL(null, repository, streamHandler);
            loader = new URLClassLoader(urls);
        } catch (IOException e) {
            System.out.println(e.toString());
        }


        //由上面的URLClassLoader加载这个servlet
        Class<?> servletClass = null;
        try {
            //获取PrintWriter
            response.setCharacterEncoding("UTF-8");
            printWriter = response.getWriter();
            servletClass = loader.loadClass(servletName);
        } catch (ClassNotFoundException | IOException e) {
            System.out.println(e.toString());
        }

//创建servlet新实例,然后调用
// service(),由它来写动态内容到响应体
        Servlet servlet = null;
        try {
            //写响应头
            String head = composeResponseHead();
            printWriter.println(head);
            servlet = (Servlet) servletClass.newInstance();
            servlet.service(request, response);
        } catch (Exception e) {
            System.out.println(e.toString());
        } catch (Throwable e) {
            System.out.println(e.toString());
        }

    }

    //生成响应头,填充变量值
    private String composeResponseHead() {
        Map<String, Object> valuesMap = new HashMap<>();
        valuesMap.put("StatusCode", "200");
        valuesMap.put("StatusName", "OK");
        valuesMap.put("ContentType", "text/html;charset=UTF-8");
        valuesMap.put("ZonedDateTime",  DateTimeFormatter.ISO_ZONED_DATE_TIME.format(ZonedDateTime.now()));
        StrSubstitutor sub = new StrSubstitutor(valuesMap);
        String responseHead = sub.replace(OKMessage);
        return responseHead;
    }
}

最后看一下实现类 helloWorld 实现规范的Servlet ,没必要的方法不展示,


import javax.servlet.*;
import java.io.IOException;

public class HelloWorldServlet implements Servlet {
    //http://localhost:8080/servlet/com.yixin.HelloWorldServlet
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        servletResponse.setCharacterEncoding("UTF-8");
        System.out.println("进入>>>>>>HelloWorldServlet.service方法");

        String doc = "Hello World !!!";
        String doc1 = "Happy Day!!!";
        servletResponse.getWriter().println(doc);
        servletResponse.getWriter().println(doc1);
    }
}
 

运行一下就可以了

public class JxdHttpServer {
    public static final String WEB_ROOT = System.getProperty("user.dir");

    public static final String FILE_ROOT = "D:\\";

    public static void main(String[] args) {
        JxdHttpConnector connector = new JxdHttpConnector();
        connector.start();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/797395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

摆动序列(力扣376)

文章目录 题目前知题解一、思路二、解题方法三、Code 总结 题目 Problem: 376. 摆动序列 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元…

c++20协程详解(四)

前言 到这就是协程的最后一节了。希望能帮到大家 代码 到这里我们整合下之前二、三节的代码 #include <coroutine> #include <functional> #include <chrono> #include <iostream> #include <thread> #include <mutex> #include <me…

JWT/JWS/JWE

JWT(JSON Web Token)&#xff1a;一种基于JSON格式&#xff0c;用于在Web应用中安全传递用户身份验证和授权信息的标准令牌&#xff0c;可以包含签名(JWS)和加密(JWE)的信息 MacAlgorithm(Message Authentication Code Algorithm)&#xff1a;消息认证码算法 HMAC(Hash-based…

2024/4/1—力扣—两数相除

代码实现&#xff1a; 思路&#xff1a;用减法模拟除法 // 用减法模拟除法 int func(int a, int b) { // a、b均为负数int ans 0;while (a < b) { // a的绝对值大于等于b&#xff0c;表示此时a够减int t b;int count 1; // 用来计数被减的次数// t > INT_MIN / 2:防止…

力扣由浅至深 每日一题.23 Nim 游戏

不要美化自己当初没有选择的那一条路 —— 24.4.7 Nim 游戏 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。你们轮流进行自己的回合&#xff0c; 你作为先手 。每一回合&#xff0c;轮到的人拿掉 1 - 3 块石头。拿掉最后一块石头的人就是获胜者…

京东获得JD商品详情 API 接口(jd.item_get)的详细使用说明,包括如何通过该接口获取商品的基本信息,包括名称、品牌、产地、规格参数等

通过调用京东商品详情API接口&#xff0c;开发者可以获取商品的基本信息&#xff0c;如名称、品牌、产地、规格参数等。此外&#xff0c;还可以获取商品价格信息&#xff0c;包括原价、促销价和活动信息等。同时&#xff0c;该接口还支持获取商品的销量、评价、图片、描述等详细…

IO学习笔记

1 什么是IO 对于任何程序设计语言而言&#xff0c;输入输出(Input/Output)系统都是非常核心的功能。程序运行需要数据&#xff0c;数据的获取往往需要跟外部系统进行通信&#xff0c;外部系统可能是文件、数据库、其他程序、网络、IO设备等等。外部系统比较复杂多变&#xff0…

微信如何识别图片中的文字?3个文字识别技巧分享

微信如何识别图片中的文字&#xff1f;微信识别图片中的文字是一项非常实用的功能&#xff0c;特别是在需要快速提取图片中的信息时。不仅如此&#xff0c;微信识别图片文字的功能也极大地提升了人们的工作和学习效率。在办公场景中&#xff0c;它可以快速将纸质文档、名片、合…

postgresql数据库|数据整合的好工具--Oracle-fdw的部署和使用

概述 Oracle_fdw 是一种postgresql外部表插件&#xff0c;可以读取到Oracle上面的数据。是一种非常方便且常见的pg与Oracle的同步数据的方法 Oracle_fdw 适用场景&#xff1a; Oracle_fdw 是一个开源的 Foreign Data Wrapper (FDW)&#xff0c;主要用于在 PostgreSQL 数据库中…

【PRO3.0 】电子面单模版请求失败问题处理

注意&#xff1a;&#xff1a;改完重启守护进程 1、文件地址&#xff1a;crmeb/services/express/storage/Express.php 行数 202 行左右&#xff0c; 方法名&#xff1a;temp() 如下如图把 POST 改成 GET 2、crmeb/services/HttpService.php 行数&#xff1a;81 行左右 方…

【MySQL】解决修改密码时报错:--skip-grant-tables option

首先我们先了解到为何会出现如上报错&#xff1a; 是因为我们在第一次配置MySQL中的my.cnf时&#xff0c;我们添加了–skip–grant-tables 选项 跳过验证身份的选项 所以&#xff0c;我们第一次登录成功后想要修改密码会出现如下报错&#xff1a; [hxiZ0jl69kyvg0h181cozuf5Z…

Vue3:自定义响应式数据-customRef(面试常问,重点!!!)

一、情景说明 我们知道&#xff0c;Vue的响应式数据效果就是&#xff0c;页面和变量的关联效果 页面一修改变量值&#xff0c;引用变量的地方就会同时更新 那么&#xff0c;假设我们有这样一个需求&#xff0c;就是&#xff0c;让响应式变量在页面修改后&#xff0c;过2秒&am…

使用Springfox Swagger实现API自动生成单元测试

目录 第一步&#xff1a;在pom.xml中添加依赖 第二步&#xff1a;加入以下代码&#xff0c;并作出适当修改 第三步&#xff1a;在application.yaml中添加 第四步&#xff1a;添加注解 第五步&#xff1a;运行成功之后&#xff0c;访问相应网址 另外&#xff1a;还可以导出…

UI自动化框架搭建以及面试题详解(上)

UI自动化框架搭建以及面试题 UI自动化面试题框架面试题那你讲下如何搭建现成的框架公司里面的框架是你搭建的么请结合你的项目讲解一下你的框架是如何搭建的 PO模式什么是 PO 模式PO 模式的封装原则有哪些 DDT驱动模式什么的项目适合ddt ddt四种模式ddt处理各种类型数据 自动化…

Lesson 9 Transformer

听课&#xff08;李宏毅老师的&#xff09;笔记&#xff0c;方便梳理框架&#xff0c;以作复习之用。本节课主要讲了seq2seq model简介&#xff0c;以及应用&#xff0c;架构&#xff08;包括encoder和decoder&#xff0c;encoder和decoder之间如何协作&#xff09;&#xff0c…

设计模式——组合模式08

组合模式&#xff1a;把类似对象或方法组合成结构为树状的设计思路。 例如部门之间的关系。 设计模式&#xff0c;一定要敲代码理解 抽象组件 /*** author ggbond* date 2024年04月06日 08:54* 部门有&#xff1a;二级部门&#xff08;下面管三级部门&#xff09; 三级部门 &a…

【Spring】AOP——使用@around实现面向切面的方法增强

工作业务中&#xff0c;有大量分布式加锁的重复代码&#xff0c;存在两个问题&#xff0c;一是代码重复率高&#xff0c;二是容易产生霰弹式修改&#xff0c;使用注解和AOP可以实现代码复用&#xff0c;简化分布式锁加锁和解锁流程。 around注解是AspectJ框架提供的&#xff0c…

uniapp方法二 激活微信小程序自带的分享功能

1、配置 onLoad(){wx.showShareMenu({withShareTicket:true,//设置下方的Menus菜单&#xff0c;才能够让发送给朋友与分享到朋友圈两个按钮可以点击menus:["shareAppMessage","shareTimeline"]}) },2、事件 onShareAppMessage(res) {if (res.from butto…

1、认识MySQL存储引擎吗?

目录 1、MySQL存储引擎有哪些&#xff1f; 2、默认的存储引擎是哪个&#xff1f; 3、InnoDB和MyISAM有什么区别吗&#xff1f; 3.1、关于事务 3.2、关于行级锁 3.3、关于外键支持 3.4、关于是否支持MVCC 3.5、关于数据安全恢复 3.6、关于索引 3.7、关于性能 4、如何…

Hashmap的工作原理

HashMap是一种常见的键值对存储数据的数据结构&#xff0c;它的工作原理可以简单概括为以下几个步骤&#xff1a; 哈希函数&#xff1a;当我们向HashMap中存入一个键值对时&#xff0c;首先会通过哈希函数将键映射到一个索引位置上。这个哈希函数将键转化为一个整数&#xff0c…