DIY-Tomcat part 3 实现对动态资源的请求

实现ServletRequest

package connector;import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
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;/*
GET /index.html HTTP/1.1Host: localhost:8888Connection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
*/public class Request implements ServletRequest {private static final int BUFFER_SIZE = 1024;private InputStream input;private String uri;public Request(InputStream input) {this.input = input;}public String getRequestURI() {return uri;}public void parse() {int length = 0;byte[] buffer = new byte[BUFFER_SIZE];try {length = input.read(buffer);} catch (IOException e) {e.printStackTrace();}StringBuilder request = new StringBuilder();for (int j=0; j<length; j++) {request.append((char)buffer[j]);}uri = parseUri(request.toString());}private String parseUri(String s) {int index1, index2;index1 = s.indexOf(' ');if (index1 != -1) {index2 = s.indexOf(' ', index1 + 1);if (index2 > index1) {return s.substring(index1 + 1, index2);}}return "";}@Overridepublic Object getAttribute(String s) {return null;}@Overridepublic Enumeration getAttributeNames() {return null;}@Overridepublic String getCharacterEncoding() {return null;}@Overridepublic void setCharacterEncoding(String s) throws UnsupportedEncodingException {}@Overridepublic int getContentLength() {return 0;}@Overridepublic String getContentType() {return null;}@Overridepublic ServletInputStream getInputStream() throws IOException {return null;}@Overridepublic String getParameter(String s) {return null;}@Overridepublic Enumeration getParameterNames() {return null;}@Overridepublic String[] getParameterValues(String s) {return new String[0];}@Overridepublic Map getParameterMap() {return null;}@Overridepublic String getProtocol() {return null;}@Overridepublic String getScheme() {return null;}@Overridepublic String getServerName() {return null;}@Overridepublic int getServerPort() {return 0;}@Overridepublic BufferedReader getReader() throws IOException {return null;}@Overridepublic String getRemoteAddr() {return null;}@Overridepublic String getRemoteHost() {return null;}@Overridepublic void setAttribute(String s, Object o) {}@Overridepublic void removeAttribute(String s) {}@Overridepublic Locale getLocale() {return null;}@Overridepublic Enumeration getLocales() {return null;}@Overridepublic boolean isSecure() {return false;}@Overridepublic RequestDispatcher getRequestDispatcher(String s) {return null;}@Overridepublic String getRealPath(String s) {return null;}
}
  • 主要是为了实现ServletRequest 接口

实现ServletResponse

package connector;import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import java.io.*;
import java.util.Locale;/*
HTTP/1.1 200 OK*/
public class Response implements ServletResponse {private static final int BUFFER_SIZE = 1024;Request request;OutputStream output;public Response(OutputStream output) {this.output = output;}public void setRequest(Request request) {this.request = request;}public void sendStaticResource() throws IOException {File file = new File(ConnectorUtils.WEB_ROOT, request.getRequestURI());try {write(file, HttpStatus.SC_OK);} catch (IOException e) {write(new File(ConnectorUtils.WEB_ROOT, "404.html"), HttpStatus.SC_NOT_FOUND);}}private void write(File resource, HttpStatus status) throws IOException {try (FileInputStream fis = new FileInputStream(resource)) {output.write(ConnectorUtils.renderStatus(status).getBytes());byte[] buffer = new byte[BUFFER_SIZE];int length = 0;while ((length = fis.read(buffer, 0, BUFFER_SIZE)) != -1) {output.write(buffer, 0, length);}}}@Overridepublic String getCharacterEncoding() {return null;}@Overridepublic ServletOutputStream getOutputStream() throws IOException {return null;}@Overridepublic PrintWriter getWriter() throws IOException {PrintWriter writer = new PrintWriter(output, true);return writer;}@Overridepublic void setContentLength(int i) {}@Overridepublic void setContentType(String s) {}@Overridepublic void setBufferSize(int i) {}@Overridepublic int getBufferSize() {return 0;}@Overridepublic void flushBuffer() throws IOException {}@Overridepublic void resetBuffer() {}@Overridepublic boolean isCommitted() {return false;}@Overridepublic void reset() {}@Overridepublic void setLocale(Locale locale) {}@Overridepublic Locale getLocale() {return null;}
}
  • 也是主要为了实现ServletRequest 接口
  • 实现getWriter()方法

实现Servlet

import connector.ConnectorUtils;
import connector.HttpStatus;
import connector.Request;import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;public class TimeServlet implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {PrintWriter out = servletResponse.getWriter();out.println(ConnectorUtils.renderStatus(HttpStatus.SC_OK));out.println("What time is it now?");out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}
  • service实时返回当前时间的具体值

实现ServletProcessor

package processor;import connector.*;import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;public class ServletProcessor {URLClassLoader getServletLoader() throws MalformedURLException {File webroot = new File(ConnectorUtils.WEB_ROOT);URL webrootUrl = webroot.toURI().toURL();return new URLClassLoader(new URL[]{webrootUrl});}Servlet getServlet(URLClassLoader loader, Request request) throws ClassNotFoundException, IllegalAccessException, InstantiationException {/*/servlet/TimeServlet*/String uri = request.getRequestURI();String servletName = uri.substring(uri.lastIndexOf("/") + 1);Class servletClass = loader.loadClass(servletName);Servlet servlet = (Servlet) servletClass.newInstance();return servlet;}public void process(Request request, Response response) throws IOException {//加载loader, 以获得具体servlet的上级目录URLClassLoader loader = getServletLoader();//通过request中的uri和loader中的上级目录加载对应的具体servlet类处理请求Servlet servlet = getServlet(loader, request);//用加载的servlet类处理请求servlet.service(request, response);
}

主要方法功能解释

  1. Class servletClass = loader.loadClass(servletName);
    loader会从webrootUrl的路径下尝试加载名字为servletName的类,这是实现请求动态资源的关键
  2. 用loader和request加载具体的servlet,再用该servlet处理请求,输出内容

改进Connector

改进Connector使其能够处理来自客户端对动态资源的访问请求

      if (request.getRequestURI().startsWith("/servlet/")) {ServletProcessor processor = new ServletProcessor();processor.process(request, response);} else {StaticProcessor processor = new StaticProcessor();processor.process(request, response);}
  • 如果请求是以/servlet/开头的,代表是对动态资源的请求,则将该请求交由ServletProcessor处理
  • 如果不是以/servlet/开头的,代表是对静态资源的请求,则交由StaticProcessor处理

测试

IDE客户端请求测试

    public static void main(String[] args)throws Exception{Socket socket = new Socket("localhost", 8888);OutputStream output = socket.getOutputStream();output.write("GET /servlet/TimeServlet HTTP/1.1".getBytes());socket.shutdownOutput();InputStream input = socket.getInputStream();byte[] buffer = new byte[2048];int length = input.read(buffer);StringBuilder response = new StringBuilder();for (int j=0; j<length; j++) {response.append((char)buffer[j]);}System.out.println(response.toString());socket.shutdownInput();socket.close();}

web浏览器测试

在这里插入图片描述
上述两种测试方法均能返回正确结果

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

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

相关文章

黑马程序员Java笔记整理(day05)

1.面向对象编程 2.用法 3.对象是什么 4.对象在计算机中是啥 5.无参与有参构造器 小结: 6.this的作用 7.小结 8.封装 9.小结 10.实体类 11.小结 12.static 13.小结 14.static修饰方法 15.static应用前景 16.几个注意事项 17.java中可以直接用类的名字创建数组&#xff0c;如: M…

Perforce SAST专家详解:自动驾驶汽车的安全与技术挑战,Klocwork、Helix QAC等静态代码分析成必备合规性工具

自动驾驶汽车安全吗&#xff1f;现代汽车的软件包含1亿多行代码&#xff0c;支持许多不同的功能&#xff0c;如巡航控制、速度辅助和泊车摄像头。而且&#xff0c;这些嵌入式系统中的代码只会越来越复杂。 随着未来汽车的互联程度越来越高&#xff0c;这一趋势还将继续。汽车越…

《Python基础》之数据加密模块hashlib的用法

目录 一、简介 二、用法 步骤一、导入hashlib库 步骤二、创建哈希对象 步骤三、往哈希对象中传值 1、可以在创建对象的时候传值 2、使用updata传值 步骤四、获取经过哈希对象加密后的值 三、注意事项 1、编码问题 2、安全性 3、多次传值 四、总结 一、简介 hashli…

QT实战--qt各种按钮实现

本篇介绍qt一些按钮的实现&#xff0c;包括正常按钮&#xff1b;带有下拉箭头的按钮的各种实现&#xff1b;按钮和箭头两部分分别响应&#xff1b;图片和按钮大小一致&#xff1b;图片和按钮大小不一致的处理&#xff1b;文字和图片位置的按钮 效果图如下&#xff1a; 详细实现…

恶补英语初级第12天,《描述进行中的动作》

对话 Where’s Sally, Jack? She’s in the garden, Jane. What’s she doing? she’s sitting under the tree. Is Tim in the garden, too? Yes, he is. He’s climbing the tree. I beg your pardon? Who’s climbing the tree? Tim is. What about the dog? The dog’…

联表查询,外键

联表查询 使用多表可以减少冗余&#xff0c;便于增删改操作&#xff0c;查询操作复杂 表与表之间通过主键和外键关联 外键 如果一张表的某个列指向另一个表的主键列 &#xff0c;就称之为外键列 -- 添加外键 alter table t_emp add constraint 外键名 foreign key (depart)…

【OJ】前K个高频单词和单词识别和两个数组的交集

个人主页 &#xff1a; zxctscl 如有转载请先通知 题目 1. 692. 前K个高频单词1.1 分析1.2 代码 2. KY264 单词识别2.1 分析2.2 代码 3. 349. 两个数组的交集3.1 分析3.2 代码 1. 692. 前K个高频单词 1.1 分析 先试用map来统计每个单词出现的次数&#xff1a; map<string,i…

分布式协同 - 分布式锁一二事儿

文章目录 导图Pre概述概述1. 分布式互斥和临界资源的协调2. 分布式锁的基本原理3. 分布式锁的实现方式a. 基于数据库实现的分布式锁b. 基于Redis实现的分布式锁c. 基于Zookeeper实现的分布式锁 4. 高并发场景下的分布式锁优化a. 分段锁&#xff08;Sharded Locks&#xff09;b.…

Vue-01

Vue框架 Vue官网&#xff1a; Vue.js 框架 数据模型和view的通信就是依靠viewmodel的关键。 目前主流版本仍然是vue2版本。 Vue快速入门 1.新建一个HTML文件&#xff0c;引入Vue.js文件。Vue.js文件是官方引入的一个文件&#xff0c;我们如果要使用Vue就必须引入这个文件。…

【微服务】Nacos

一、安装 1、官网地址&#xff1a;https://nacos.io/download/nacos-server/ 2、启动&#xff1a;找到bin目录下的startup.cmd双击启动&#xff0c;或者打开一个命令窗口输入&#xff1a; startup.cmd -m standalone双击启动后如下&#xff1a;可以访问控制台地址 访问后的…

【Docker项目实战】使用Docker部署Paint Board在线创意画板工具

【Docker项目实战】使用Docker部署Paint Board在线创意画板工具 一、 Paint Board介绍1.1 Paint Board简介1.2 主要功能1.3 主要使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版…

在oracle下载jdk显示400 Bad Request Request Header Or Cookie Too Large

下载JDK17&#xff0c;官网地址&#xff1a;【https://www.oracle.com/cn/java/technologies/downloads/#jdk17-windows】 问题&#xff1a; 出现 400 Bad Request: Request Header Or Cookie Too Large 错误&#xff0c;通常是由于浏览器存储的 Cookies 或请求头过大所导致的…

实现一个Vue自定义指令

在 Vue 中&#xff0c;自定义指令允许你为 DOM 元素添加特定的行为或功能。下面是一个实现 Vue 自定义指令的简单示例&#xff0c;展示了如何创建一个指令&#xff0c;使得元素在鼠标悬停时改变背景色。 1. 创建自定义指令 在 Vue 2.x 中&#xff0c;你可以在 Vue.directive …

开发需求总结19-vue 根据后端返回一年的数据,过滤出符合条件数据

需求描述&#xff1a; 定义时间分界点&#xff1a;每月26号8点&#xff0c;过了26号8点则过滤出data数组中符合条件数据下个月的数据&#xff0c;否则过滤出当月数据 1.假如现在是2024年11月14日&#xff0c;那么过滤出data数组中日期都是2024-11月的数据&#xff1b; 2.假如…

2025 - AIDD - python的autodock vina 批量分子对接改进版本2.0-全自动对接,完全全自动对接

2025 - AIDD - python的autodock vina 批量分子对接改进版本2.0-全自动对接&#xff0c;完全全自动对接 import warnings from pathlib import Path import subprocess from itertools import product import numpy as np import pandas as pd from MDAnalysis import Univers…

【uniapp】轮播图

前言 Uniapp的swiper组件是一个滑块视图容器组件&#xff0c;可以在其中放置多个轮播图或滑动卡片。它是基于微信小程序的swiper组件进行封装&#xff0c;可以在不同的平台上使用&#xff0c;如微信小程序、H5、App等。 效果图 前端代码 swiper组件 <template><vi…

由于导包而引发的错误

今天在调试时发现删除功能无论如何都无法实现&#xff0c;于是调试找到了mapper层的错误但不知道为什么报错。以下是报错信息。 Caused by: org.apache.ibatis.binding.BindingException: Parameter userIds not found. Available parameters are [arg0, collection, list]at o…

网络安全-加密

1.概念 明文&#xff1a;需要被加密的消息&#xff0c;一般是人直接可以阅读理解的内容。(plaintext)密文: 被加密后的消息&#xff0c;一般是人不可直接阅读并理解的。(ciphertext)加密:将明文转换成密文的过程。(encryption)解密:将密文恢复成明文的过程。(decryption)加密…

音视频入门基础:MPEG2-TS专题(9)——FFmpeg源码中,解码TS Header的实现

一、引言 FFmpeg源码对MPEG2-TS传输流/TS文件解复用时&#xff0c;在通过read_packet函数读取出一个transport packet后&#xff0c;会调用handle_packet函数来处理该transport packet&#xff1a; static int handle_packets(MpegTSContext *ts, int64_t nb_packets) { //..…

Pytorch使用手册-使用 TensorBoard 可视化模型、数据和训练过程(专题十)

在 60 分钟速成课程中,我们展示了如何加载数据,将其传递通过我们定义的作为 nn.Module 子类的模型,训练该模型并在测试数据上进行测试。为了查看发生了什么,我们在模型训练过程中打印一些统计信息,以便了解训练是否进展顺利。然而,我们可以做得更好:PyTorch 与 TensorBo…