【仿写tomcat】四、解析http请求信息,响应给前端,HttpServletRequest、HttpServletResponse的简单实现

news/2024/5/19 6:03:37 标签: tomcat, http, java, 反射, 代理
http://www.w3.org/2000/svg" style="display: none;">

思考

在解析请求之前我们要思考一个问题,我们解析的是其中的哪些内容?

对于最基本的实现,当然是请求类型请求的url以及请求参数,我们可以根据请求的类型作出对应的处理,通过url在我们的mapstore中找到servlet,那么请求的参数我们是不是还没有储存的地方呢?

所以我们要先定义一个类来存储参数

HttpServletRequest

当然你也可以通过接口的形式来规范方法,我在这里进行的是最基本的仿写,就不做复杂的设计了,下面这个类是存储请求信息的类,我们在后续还会进行扩展,因我们还要实现cookie、session等功能

java">package com.tomcatServer.domain;

import java.util.HashMap;
import java.util.Map;

/**
 * http servlet请求
 *
 * @author ez4sterben
 * @date 2023/08/15
 */
public class HttpServletRequest {

    private final Map<String,String> params = new HashMap<>();

    private String requestBody;

    public String getRequestBody() {
        return requestBody;
    }

    public void setRequestBody(String requestBody) {
        this.requestBody = requestBody;
    }

    public Map<String, String> getParams() {
        return params;
    }

    public String getParam(String paramName){
        return params.get(paramName);
    }
}


httpHttpServletRequest_47">http请求解析,HttpServletRequest

我们再给服务器发一个带参数的请求看看http信息是什么样子的
http://localhost:8080/test?aaa=aaa
https://img-blog.csdnimg.cn/1aad17aed1a149b6b16d71ea36022a5f.png" alt="在这里插入图片描述" />
这个信息的第一行就是请求的类型、url和参数,那么我们直接对这里进行解析就行了

java">// 解析request param
String url = requestData.split(" ")[1];
String[] urlContent = url.split("\\?");
// ?前的是请求地址
String requestPath = urlContent[0];
// 问号后的是参数
String params = urlContent[1];
// 参数按照=分割
String[] paramsKeyValue = params.split("=");

存入map

java">// 设置请求参数
        HttpServletRequest request = new HttpServletRequest();
        Map<String, String> paramsMap = request.getParams();
        for (int i = 0; i < paramsKeyValue.length; i += 2) {
            paramsMap.put(paramsKeyValue[i],paramsKeyValue[i+1]);
        }

响应类HttpServletResponse

这个类中要注意的是我们要给返回的信息拼上一个头部信息代表着成功编号和信息类型

java">package com.tomcatServer.domain;

import java.io.PrintWriter;

/**
 * http servlet响应
 *
 * @author ez4sterben
 * @date 2023/08/15
 */
public class HttpServletResponse {

    private final PrintWriter out;

    private static final String response;

    public HttpServletResponse(PrintWriter out) {
        this.out = out;
    }

    static {
        response = "HTTP/1.1 200 OK\r\n" +
                "Content-Type: text/plain\r\n" +
                "\r\n";
    }

    /**
     * 写
     *
     * @param content 内容
     */
    public void write(String content) {
        out.println(response + content);
    }

}


代理

既然实现到这里了,自然会想到,执行谁的响应呢?

没错,当然是servlet中的,那就需要我们使用代理来调用其中的方法了

java">package com.tomcatServer.utils;

import com.tomcatServer.annotation.WebServlet;
import com.tomcatServer.domain.HttpServletRequest;
import com.tomcatServer.domain.HttpServletResponse;
import com.tomcatServer.servlet.MapStore;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * servlet工具类
 *
 * @author tomcatProject.ez4sterben
 * @date 2023/08/15
 */
public class ServletUtil {

    /**
     * 是web servlet
     *
     * @param className 类名
     * @return {@link Boolean}
     */
    public static Boolean isWebServlet(String className){
        try {
            Class<?> aClass = Class.forName(className);
            WebServlet annotation = aClass.getAnnotation(WebServlet.class);
            if (annotation == null){
                return Boolean.FALSE;
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return Boolean.TRUE;
    }


    /**
     * 初始化servlet
     *
     * @param className 类名
     */
    public static void initServlet(String className){
        try {
            Class<?> aClass = Class.forName(className);
            String url = aClass.getAnnotation(WebServlet.class).value();
            if (url.startsWith("/")) {
                MapStore.servletMap.put(url,aClass);
            }else {
                MapStore.servletMap.put("/" + url,aClass);
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 调用get方法
     *
     * @param url     url
     * @param request
     */
    public static void invokeGet(String url, HttpServletRequest request, HttpServletResponse response){
        Class<?> aClass = MapStore.servletMap.get(url);
        try {
            Method doGet = aClass.getDeclaredMethod("doGet", HttpServletRequest.class, HttpServletResponse.class);
            Object instance = aClass.newInstance();
            doGet.invoke(instance, request, response);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 调用后
     *
     * @param url      url
     * @param request  请求
     * @param response 响应
     */
    public static void invokePost(String url, HttpServletRequest request, HttpServletResponse response){
        Class<?> aClass = MapStore.servletMap.get(url);
        try {
            Method doPost = aClass.getDeclaredMethod("doPost", HttpServletRequest.class, HttpServletResponse.class);
            Object instance = aClass.newInstance();
            doPost.invoke(instance, request, response);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}

HttpServlet规范

接下来定义一个抽象类来规范servlet类

java">package com.tomcatServer.domain;

import java.io.IOException;

/**
 * http servlet
 *
 * @author ez4sterben
 * @date 2023/08/15
 */
public abstract class HttpServlet {

    /**
     * 做得到
     *
     * @param request  请求
     * @param response 响应
     * @throws IOException ioexception
     */
    public abstract void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException;

    /**
     * 做帖子
     *
     * @param request  请求
     * @param response 响应
     * @throws IOException ioexception
     */
    public abstract void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException;



}

然后在项目中创建一个测试的servlet类
https://img-blog.csdnimg.cn/63c25daea5bc429ead94ec9af9876e9d.png" alt="在这里插入图片描述" />

java">package tomcatProject.com.ez4sterben.servlet;

import com.tomcatServer.annotation.WebServlet;
import com.tomcatServer.domain.HttpServlet;
import com.tomcatServer.domain.HttpServletRequest;
import com.tomcatServer.domain.HttpServletResponse;


/**
 * 登录servlet
 *
 * @author tomcatProject.ez4sterben
 * @date 2023/08/15
 */
@WebServlet("/test")
public class TestServlet extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        response.write(request.getParam("aaa"));
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) {

    }
}

请求测试

java">package com.tomcatServer.socket;

import com.tomcatServer.domain.HttpServletRequest;
import com.tomcatServer.domain.HttpServletResponse;
import com.tomcatServer.utils.ScanUtil;
import com.tomcatServer.utils.ServletUtil;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;

/**
 * 套接字存储
 *
 * @author ez4sterben
 * @date 2023/08/15
 */
public class SocketStore {

    private static ServerSocket socket;

    public static void connect(Integer port) throws IOException {
        socket = new ServerSocket(port);
    }

    public static void close() throws IOException {
        socket.close();
    }

    public static ServerSocket getSocket() {
        return socket;
    }


    /**
     * 处理请求
     *
     * @throws IOException ioexception
     */
    public static void handleRequest(Socket accept) throws IOException {
        // 获取输入输出流
        BufferedReader in = new BufferedReader(new InputStreamReader(accept.getInputStream()));
        PrintWriter out = new PrintWriter(accept.getOutputStream(), true);
        // 定义字符串接收Http协议内容
        String inputLine;
        StringBuilder requestData = new StringBuilder();
        // 读取数据
        while ((inputLine = in.readLine()) != null && !inputLine.isEmpty()) {
            requestData.append(inputLine).append("\r\n");
        }
        System.out.println(requestData);
        
        if (!requestData.toString().trim().equals("")){
                handleGetAndPostReuqest(in, out, String.valueOf(requestData));
            }
        // 关闭资源
        accept.close();
    }

    /**
     * 处理post请求
     *
     * @param in          在
     * @param requestData 请求数据
     * @throws IOException ioexception
     */
    private static void handleGetAndPostReuqest(BufferedReader in,PrintWriter out, String requestData) throws IOException {
        // 解析request param
        String url = requestData.split(" ")[1];
        String[] urlContent = url.split("\\?");
        String requestPath = urlContent[0];
        String params = urlContent[1];
        String[] paramsKeyValue = params.split("=");

        // 设置请求参数
        HttpServletRequest request = new HttpServletRequest();
        Map<String, String> paramsMap = request.getParams();
        for (int i = 0; i < paramsKeyValue.length; i += 2) {
            paramsMap.put(paramsKeyValue[i],paramsKeyValue[i+1]);
        }
        if (requestData.contains("GET")){
            // 设置响应内容
            HttpServletResponse response = new HttpServletResponse(out);
            ServletUtil.invokeGet(requestPath,request,response);
        }
    }

}

访问http://localhost:8080/test?aaa=123
因为servlet中的操作是返回参数,所以结果应该为123

java">response.write(request.getParam("aaa"));

https://img-blog.csdnimg.cn/49c933e17a4e43b8b1d2695e8a473e64.png" alt="在这里插入图片描述" />
下一篇将会实现对html页面的解析


http://www.niftyadmin.cn/n/4945492.html

相关文章

005-Spring 扩展点 :PostProcess

目录 Spring 扩展点 &#xff1a;PostProcess介绍PostProcess大纲文字明细使用方法示例Autowired 功能实现Resource 功能实现 后记 Spring 扩展点 &#xff1a;PostProcess 介绍 Spring 核心做的事情其实很简单就是&#xff1a;控制反转和依赖注入 也就是把 Class 解析为 Bea…

C语言好题解析(二)

目录 递归类型例题1例题2例题3例题4例题5例题6 递归类型 例题1 根据下面递归函数&#xff1a;调用函数Fun(2)&#xff0c;返回值是多少&#xff08; &#xff09;int Fun(int n) {if (n 5)return 2;elsereturn 2 * Fun(n 1); } A.2 B.4 C.8 D.16【答案】 D 【分析】 …

AutoSAR配置与实践(配置篇)RTE对Ports的支持 – C/S原理进阶

传送门 点击返回 ->AUTOSAR配置与实践总目录 AutoSAR配置与实践(配置篇)RTE对Ports的支持 – C/S原理进阶 一、 Polling和Waiting类型的 C/S接口执行流程详解1.1 Polling流程详解1.2 Waiting流程详解二、存储请求信息的数据形式2.1 Polling 类型接口执行状态存储形式2.2 W…

《机器学习系统:设计与实现》读书笔记一

最近几年一直在做算法工程的工作&#xff0c;对机器学习系统有所涉猎&#xff0c;也很感兴趣。近期发现一本开源书籍《机器学习系统&#xff1a;设计与实现》。去图书馆找了它的纸质版&#xff0c;发现内容不尽相同。在这里结合两者做一个读书笔记。本文是第一篇&#xff0c;主…

从零实战SLAM-第十课(回环检测与建图)(完)

在七月算法报的班&#xff0c;老师讲的蛮好。好记性不如烂笔头&#xff0c;关键内容还是记录一下吧&#xff0c;课程入口&#xff0c;感兴趣的同学可以学习一下。 --------------------------------------------------------------------------------------------------------…

从入门到精通Python隧道代理的使用与优化

哈喽&#xff0c;Python爬虫小伙伴们&#xff01;今天我们来聊聊如何从入门到精通地使用和优化Python隧道代理&#xff0c;让我们的爬虫程序更加稳定、高效&#xff01;今天我们将对使用和优化进行一个简单的梳理&#xff0c;并且会提供相应的代码示例。 1. 什么是隧道代理&…

广联达OA前台sql注入+后台文件上传漏洞复现分析

文章目录 前言资产特征前台sql注入后台文件上传解决办法 前言 最近看到广联达OA的前端sql注入和后端文件上传漏洞联动的poc 广联达科技股份有限公司以建设工程领域专业应用为核心基础支撑&#xff0c;提供一百余款基于“端云大数据”产品/服务&#xff0c;提供产业大数据、产业…

JavaWeb-DAO设计模式

目录 DAO设计模式 1.认识DAO 2.DAO各部分的详解 3.DAO设计模式流程 DAO设计模式 1.认识DAO DAO(Data Acess Object 数据库访问对象)的主要功能是操作数据库&#xff0c;所以DAO在标准开发架构中数据数据层&#xff0c;以下是标准开发的架构 客户层&#xff1a;目前使用B/…