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

news/2024/10/23 7:32:31/

访问html页面

如果我们想访问html页面其实就是将本地的html文件以流的方式响应给前端即可,下面我们对HttpResponseServlet这个类做一些改造

package com.tomcatServer.domain;import com.tomcatServer.utils.ScanUtil;import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;/*** http servlet响应** @author ez4sterben* @date 2023/08/15*/
public class HttpServletResponse {private final PrintWriter out;private static final String response;private static final String htmlResponse;public HttpServletResponse(PrintWriter out) {this.out = out;}static {response = "HTTP/1.1 200 OK\r\n" +"Content-Type: text/plain\r\n" +"\r\n";htmlResponse = "HTTP/1.1 200 OK\r\n" +"Content-Type: text/html\r\n" +"\r\n";}/*** 写** @param content 内容*/public void write(String content) {out.println(response + content);}/*** 编写html** @param htmlFileName html文件名字* @throws IOException ioexception*/public void writeHtml(String htmlFileName) throws IOException {Path path = Paths.get(ScanUtil.WEB_APP_PATH + "\\" + htmlFileName);byte[] bytes = Files.readAllBytes(path);out.println(htmlResponse + new String(bytes, StandardCharsets.UTF_8));}
}

writeHtml这个方法将会读取webApp下面的html文件,注意只读取下面一级文件中的html文件,然后将这个文件以二进制流的形式转换成字符串拼接到上面定义的html格式的响应头。

处理静态资源请求

当我们有了解析html文件的方法后,下面要做的就是处理静态资源,也就是判断一下请求路径中是否有.html这个字符串,有的话就把这次请求当做静态资源请求处理,没有的话再交给GET或者POST请求。这个逻辑将添加在SocketStore中,下面展示更改玩的SocketStore代码

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");}// 解析request paramString url = requestData.toString().split(" ")[1];// 处理静态资源if(url.contains(".html")){String staticSourceName = (url.split(".html")[0] + ".html").substring(1);HttpServletResponse response = new HttpServletResponse(out);response.writeHtml(staticSourceName);}else {// 处理GET与POST请求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("POST")) {// 解析request bodyint contentLength = Integer.parseInt(requestData.split("Content-Length: ")[1].split("\r\n")[0]);StringBuilder requestBody = new StringBuilder();for (int i = 0; i < contentLength; i++) {requestBody.append((char) in.read());}// 设置request bodyrequest.setRequestBody(String.valueOf(requestBody));// 设置响应内容HttpServletResponse response = new HttpServletResponse(out);ServletUtil.invokePost(requestPath,request,response);}if (requestData.contains("GET")){// 设置响应内容HttpServletResponse response = new HttpServletResponse(out);ServletUtil.invokeGet(requestPath,request,response);}}}

访问测试

接下来我们在index.html里面写点东西并访问一下试试
在这里插入图片描述
http://localhost:8080/index.html
在这里插入图片描述

路由支持

其实刚才完成这个功能的时候就会发现,如何访问子目录里面的html呢?
这里其实就要写一个小方法来支持路由重定向了,下面编写一个HttpUtil

package com.tomcatServer.utils;import com.tomcatServer.domain.HttpServletRequest;
import com.tomcatServer.domain.HttpServletResponse;import java.io.IOException;public class HttpUtil {private final String redirectPath;public HttpUtil(String redirectPath) {this.redirectPath = redirectPath;}public void forward(HttpServletRequest request, HttpServletResponse response) throws IOException {response.writeHtml(redirectPath);}
}

对HttpServletRequest做一些改进,提供一个加载静态资源的方法。

    public HttpUtil getStaticSource(String path){return new HttpUtil(path);}

其实这样我们的功能就完成了,写一个servlet以及html来测试一下

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;import java.io.IOException;@WebServlet("/router")
public class RouterServlet extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {request.getStaticSource("WEB-INF/page/"+request.getParam("path")+".html").forward(request, response);}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {doGet(request, response);}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多线程改进

为什么要在这里谈多线程改进呢,其实是因为我们最近本的接收请求,响应请求,响应页面以及完成了,接下来要考虑的就是如何支持并发处理请求如何配置并发数如何配置端口等优化问题。

如果想实现并发处理请求的话,实际上只需要预先定义一个线程池即可,把处理请求的方法交给一个任务类并且实现Runnable接口,当然我们后面会再优化这种方案。

package com.tomcatServer.task;import com.tomcatServer.socket.SocketStore;import java.io.IOException;
import java.net.Socket;public class RequestTask implements Runnable{private final Socket accept;public RequestTask(Socket accept) {this.accept = accept;}@Overridepublic void run() {try {SocketStore.handleRequest(accept);} catch (IOException e) {throw new RuntimeException(e);}}
}
        ...public static ExecutorService threadPool;...// 5.初始化线程池threadPool = Executors.newFixedThreadPool(10);// 6.处理http请求try {SocketStore.connect(PORT);while (true){Socket accept = SocketStore.getSocket().accept();if (accept != null){threadPool.submit(new RequestTask(accept));}}} catch (IOException e) {throw new RuntimeException(e);}finally {SocketStore.close();}

http://www.ppmy.cn/news/1038670.html

相关文章

前端笔试+面试分享

以下是个人线下面试遇到的真实的题&#xff0c;仅供参考和学习 1. css 选择符有哪些&#xff1f;哪些属性可以继承&#xff1f;优先级算法加何计算&#xff1f; CSS选择符有很多种&#xff0c;例如类型选择器、类选择器、ID选择器、属性选择器、伪类选择器、伪元素选择器等。 …

二、编写第一个 Spring MVC 程序(总结项目报 404 问题以及 Spring MVC 的执行流程)

文章目录 一、编写第一个 Spring MVC 程序二、项目运行时报 404错误原因总结三、Spring MVC 的执行流程 一、编写第一个 Spring MVC 程序 创建 maven 项目&#xff0c;以此项目为父项目&#xff0c;在父项目的 pom.xml 中导入相关依赖 <dependencies><dependency…

ffmpeg将图片压缩成视频过程中的问题记录

问题描述&#xff1a;服务器集群上在使用如下命令对img_path文件夹下的图片&#xff08;图片名1.jpg……300.jpg&#xff09;进行批量合成视频过程中,ffmpeg创建完视频文件后&#xff0c;写入过程中&#xff0c;自动kill,捕获异常为空。问题原因&#xff1a;集群pods的内存不够…

软件项目验收测试:验证软件功能与性能的有效手段

软件验收测试是软件产品周期中的最后一个测试活动&#xff0c;因此也叫交付测试。目的是确保软件准备就绪&#xff0c;并且可以让最终用户将其用于执行软件的既定功能和任务。 一、软件项目验收测试的重要性 1、软件项目验收测试是确保软件交付前质量的重要环节。在软件项目开…

Java中的枚举类型

一&#xff0c;什么是枚举 在Java中&#xff0c;枚举&#xff08;Enumeration&#xff09;是一种特殊的数据类型&#xff0c;它允许我们定义一个固定数量的常量集合。枚举类型在Java中是通过关键字enum来定义的。每个枚举常量都是枚举类型的实例&#xff0c;它们在枚举类型中以…

将Swift Package构建为通用二进制文件 Universal Binary

将Swift软件包构建为通用二进制文件 因此&#xff0c;在苹果在WWDC 2020期间宣布他们将把Mac从英特尔处理器过渡到苹果硅之后&#xff0c;现在是时候让每个人都准备好他们的软件了。 对大多数人来说&#xff0c;这次过渡可能更容易一些&#xff0c;特别是那些已经在iOS上支持a…

如何发布自己的小程序

小程序的基础内容组件 text&#xff1a; 文本支持长按选中的效果 <text selectable>151535313511</text> rich-text: 把HTML字符串渲染为对应的UI <rich-text nodes"<h1 stylecolor:red;>123</h1>"></rich-text> 小程序的…

Nginx反向代理技巧

跨域 作为一个前端开发者来说不可避免的问题就是跨域&#xff0c;那什么是跨域呢&#xff1f; 跨域&#xff1a;指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的&#xff0c;是浏览器对javascript施加的安全限制。浏览器的同源策略是指协议&#xff0c;域名…