当前位置: 首页 > news >正文

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

思考

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

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

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

HttpServletRequest

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

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);}
}

http请求解析,HttpServletRequest

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

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

存入map

// 设置请求参数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

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

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中的,那就需要我们使用代理来调用其中的方法了

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类

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类
在这里插入图片描述

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 {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) {response.write(request.getParam("aaa"));}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) {}
}

请求测试

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 paramString 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

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

在这里插入图片描述
下一篇将会实现对html页面的解析

【仿写tomcat】五、响应静态资源(访问html页面)、路由支持以及多线程改进

http://www.lryc.cn/news/132881.html

相关文章:

  • FL Studio21.1中文完整版Win/Mac
  • 基于Mysql+Vue+Django的协同过滤和内容推荐算法的智能音乐推荐系统——深度学习算法应用(含全部工程源码)+数据集
  • Python Web开发 Django 简介
  • HAproxy搭建web集群
  • 临时用工小程序:一款便捷的用工管理软件
  • Android Studio 之 Android 中使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理
  • CSDN编程题-每日一练(2023-08-20)
  • 大数据:NumPy进阶应用详解
  • new String创建几个对象
  • 【路由协议】使用按需路由协议和数据包注入的即时网络模拟传递率(PDR)、总消耗能量和节点消耗能量以及延迟研究(Matlab代码实现)
  • c#实现依赖注入
  • 算法通关村十一关 | 位运算实现加法和乘法
  • C++笔记之条件变量(Condition Variable)与cv.wait 和 cv.wait_for的使用
  • Dubbo之DubboBootstrap源码解析
  • SpringBoot + Vue 微人事 项目 (第八天)
  • 人工智能引领图文扫描新趋势
  • ChatGPT在智能城市规划和交通优化中的应用如何?
  • 探索Perfetto:开源性能追踪工具的未来之光
  • A*算法图文详解
  • [MySQL] — 数据类型和表的约束
  • JetBrains IDE远程开发功能可供GitHub用户使用
  • LVS 负载均衡集群
  • Mongodb Ubuntu安装
  • 【Spring Boot 源码学习】自动装配流程源码解析(下)
  • 基于微信小程序的毕业设计题目200例
  • 【数据管理】什么是数据管理?
  • [oneAPI] 手写数字识别-LSTM
  • 通过css设置filter 属性,使整个页面呈现灰度效果,让整个网页变灰
  • ahooks.js:一款强大的React Hooks库及其API使用教程(一)
  • 拟合圆算法源码(商业)