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

ui设计零基础好学吗关键词优化的建议

ui设计零基础好学吗,关键词优化的建议,设计网站卖钱,没经验的人开什么店好Tomcat 是一个广泛使用的开源 Servlet 容器,用于运行 Java Web 应用程序。深入理解 Tomcat 的工作原理对于 Java 开发者来说是非常有价值的。本文将带领大家手动实现一个简易版的 Tomcat,通过这个过程,我们可以更清晰地了解 Tomcat 是如何处理…

        Tomcat 是一个广泛使用的开源 Servlet 容器,用于运行 Java Web 应用程序。深入理解 Tomcat 的工作原理对于 Java 开发者来说是非常有价值的。本文将带领大家手动实现一个简易版的 Tomcat,通过这个过程,我们可以更清晰地了解 Tomcat 是如何处理 HTTP 请求和响应的。

        tomcat涉及到的知识点较多,主要有注解、抽象类、反射、IO流等,对基础掌握度要求较高,掌握这些基础后,我们开始手写tomcat

一、创建包

一个基本的 Tomcat 主要完成以下几个核心功能:

  1. 监听端口:等待客户端的 HTTP 请求。
  2. 解析请求:从客户端请求中提取关键信息,如请求方法、请求路径等。
  3. 处理请求:根据请求信息调用相应的处理逻辑。
  4. 返回响应:将处理结果封装成 HTTP 响应返回给客户端。

根据以上功能,我们创建如下图所示的包

--tomcat类的作用是启动整个tomcat容器

--webapp包下存放你自己创建的servlet动态资源

--httpServletRe包下有两个类HttpServletRequest和HttpservletResponse,这两个类可以说是与前端请求直接关联。

        在前端的请求信息中,请求方式和访问路径都要放在HttpServletRequest类中,可以说是相当的重要,我们可以通过socket将前端信息装到该类中,具体写法之后细讲,也就是说我们知道该类有请求方式和访问路径,通过和项目本身的资源对比从而定位到某个实际的静态资源或动态资源

而HttpServletResponse则是向前端发送我们自己写的消息,依赖outputStream来完成,该消息需要遵循响应信息的特定格式,之后的工具类中会给出

--servlet包下则是仿照Java类库中的servlet继承关系,创建了servlet接口,Gservlet抽象类和Httpservlet抽象类

--util包下存放两个工具类,一个类的作用是找到webapp下所有servlet类的类路径,用来进行反射;

一个类的作用是创建响应消息的返回格式,包展开如下:

二、写tomcat逻辑

要想得到前端发送的请求,我们首先需要创建一个ServerSocket对象实例来接收:

ServerSocket serverSocket = new ServerSocket(9090);
while(true){Socket socket = serverSocket.accept();
}

写一个while语句循环接收前端请求,一旦接收到请求,我们就可以创建输入流对象,将前端发送的消息存下来,在这里我们先只获取请求行的信息也就是第一行的信息

BufferedReader bufferedReader = new BufferedReader(new                             InputStreamReader(socket.getInputStream()));
String s = bufferedReader.readLine();

可以看到,浏览器中第一行有请求方式和访问路径,我们是以字符串形式接收的第一行数据,所以可以通过split()方法将请求方式和访问路径分开

String[] s1 = s.split(" ");

tomcat代码展示:(端口的话可以自己选,我写的是9090,tomcat默认端口是8080)

三、写HttpServletRequest的逻辑

得到请求方式和访问路径之后,我们需要将请求方式和访问路径封装到HttpServletRequest类中,在HttpServletRequest类中定义字符串类型的变量url和method,创建getter和setter方法:

public class HttpServletRequest {private String url;private String method;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}
}

四、补充tomcat逻辑

我们已经定义好HttpServletRequest类,接下来我们将tomcat类中拿到的请求方式和访问路径赋给该类中的变量method和url,首先在tomcat创建HttpServletRequest类的实例对象request,调用request的set方法,入参是inputStream获取到的请求方式和访问路径

代码如下:

写到该阶段我们可以先测试一下,在HttpServletRequest中重写toString方法,在tomcat中调用

到浏览器上输入http://localhost:9090,发现控制台输出:

请求方法和访问路径成功封装到了request中,我们继续下面的逻辑。

五、仿写servlet的继承关系

servlet包下是仿照Java类库中的servlet继承关系,创建了servlet接口,Gservlet抽象类和Httpservlet抽象类,我们现在在这三个类中添加逻辑

Servlet接口

该接口中定义以下方法:init方法、service方法和destroy方法,service方法用来判断是get请求还是post请求,在本接口中只定义,在HttpServlet抽象类中实现。其中有两个入参,HttpServletRequest类型的request和HttpservletResponse的response,之前request对象封装过请求方式,该方法会通过拿到入参的请求方式判断是get请求还是post请求

package com.qcby.servlet;import com.qcby.httpServletRe.HttpServletRequest;
import com.qcby.httpServletRe.HttpServletResponse;public interface Servlet {void init();void service(HttpServletRequest request, HttpServletResponse response) throws Exception;void destroy();
}

Gservlet抽象类

该抽象类继承Servlet接口并实现init方法和destroy方法,这两种方法我们不写实际功能,了解java类库中这两种方法的作用即可

package com.qcby.servlet;public abstract class Gservlet implements Servlet{@Overridepublic void init() {System.out.println("初始化");}@Overridepublic void destroy() {System.out.println("销毁");}
}

HttpServlet抽象类

该类继承Gservlet抽象类,实现了Servlet接口中的service方法,此外HttpServlet类中还增加了两种方法,doGet方法和doPost方法,相信学过servlet的小伙伴们并不陌生,doGet方法和doPost方法作为抽象方法不具体实现,子类也就是我们自己创建的servlet类继承该类时就必须实现该方法,至于service方法是用来区分get方法和post方法的,所以之前的request入参就是为了提供method做if判断

package com.qcby.servlet;import com.qcby.httpServletRe.HttpServletRequest;
import com.qcby.httpServletRe.HttpServletResponse;import java.io.IOException;public abstract class HttpServlet extends Gservlet{@Overridepublic void service(HttpServletRequest request, HttpServletResponse response) throws Exception{if(request.getMethod().equals("GET")){doGet(request,response);}else{doPost(request,response);}}public abstract void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException;public abstract void doPost(HttpServletRequest request, HttpServletResponse response);
}

六、创建注解类WebSocket

在工具包下创建WebSocket注解类,该注解类的作用是定义servlet类的url路径

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface WebSocket {public String url() default "";
}

七、创建servlet容器

tomcat启动时,Servlet 容器需要将客户端请求的 URL 路径映射到具体的 Servlet 上,以便正确处理请求。为了实现这一功能,容器使用 Map 来存储 URL 路径和 Servlet 名称或实例之间的映射关系。

要想获取URL路径和Servlet实例对象,我们首先要通过反射获取到类的类信息,而获取类信息需要获取类的全路径,所以写一个工具类获取webapp包下所有类的全路径,然后初始化map容器

import com.qcby.servlet.HttpServlet;import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;public class FindServletAllPath {public static HashMap<String, HttpServlet> map = new HashMap<>();public static List<String> getClassPaths(String packageName) throws IOException, ClassNotFoundException {List<String> classPaths = new ArrayList<>();// 将包名转换为文件系统路径String path = packageName.replace('.', '/');// 获取类加载器ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// 获取指定路径下的所有资源Enumeration<URL> resources = classLoader.getResources(path);while (resources.hasMoreElements()) {URL resource = resources.nextElement();// 获取资源的文件路径String filePath = resource.getFile();// 递归扫描目录scanDirectory(new File(filePath), packageName, classPaths);}return classPaths;}/*** 递归扫描目录,查找所有的 .class 文件* @param directory 要扫描的目录* @param packageName 当前包名* @param classPaths 存储类路径的列表*/private static void scanDirectory(File directory, String packageName, List<String> classPaths) {if (!directory.exists()) {return;}// 获取目录下的所有文件和文件夹File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isDirectory()) {// 递归扫描子目录scanDirectory(file, packageName + "." + file.getName(), classPaths);} else if (file.getName().endsWith(".class")) {// 获取类名String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);classPaths.add(className);}}}}static{try {// 指定要扫描的包名String packageName = "com.qcby.webapp";// 获取类路径列表List<String> classPaths = getClassPaths(packageName);// 打印类路径for (String classPath : classPaths) {Class<?> aClass = Class.forName(classPath);WebSocket annotation = aClass.getAnnotation(WebSocket.class);HttpServlet o = (HttpServlet) aClass.newInstance();map.put(annotation.url(),o);}} catch (Exception e) {e.printStackTrace();}}
}

我们把这个过程装入static块中,这样在类加载时就能完成容器的映射

八、创建servlet动态资源

在webapp包下创建一个servlet类,继承HttpServlet抽象类,重写doGet和doPost方法,各自添加一个输出语句,添加WebSocket注解,确定该类的url路径

import com.qcby.httpServletRe.HttpServletRequest;
import com.qcby.httpServletRe.HttpServletResponse;
import com.qcby.servlet.HttpServlet;
import com.qcby.util.WebSocket;import java.io.IOException;@WebSocket(url = "/first")
public class FirstServlet extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {System.out.println("first的doGet方法被调用");}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) {System.out.println("first的doPost方法被调用");}
}

九、补充tomcat逻辑

前端发送的请求方式和url路径已经封装到request对象当中,map中k值存放着请求路径,通过map映射可以找到对应的servlet实例对象,此时servlet的引用类型是父类类型,我们可以直接调用父类的方法service,有两个参数request和response,创建一个response对象放入对应参数位置

if(FindServletAllPath.map.containsKey(request.getUrl())){HttpServlet servlet = FindServletAllPath.map.get(request.getUrl());servlet.service(request,response);
}

进入service方法后,会通过获取request的请求方式判断是执行doget方法还是doPost方法,因为方法被子类重写,所以最终会调用到实际servlet的doget方法或者doPost方法

十、写HttpServletResponse逻辑

我们已经完成了请求的接受和处理,接下来需要将信息返回给前端

创建BufferOutputStream包装流将socket.outputStream包装后进行发送,需要注意的是,发送回前端的数据需要遵循特定的响应格式,我们再util包下创建一个工具类将数据封装到固定格式中

package com.qcby;public class ResponseUtil {public  static  final String responseHeader200 = "HTTP/1.1 200 \r\n"+"Content-Type:text/html; charset=utf-8 \r\n"+"\r\n";public static String getResponseHeader404(){return "HTTP/1.1 404 \r\n"+"Content-Type:text/html; charset=utf-8 \r\n"+"\r\n" + "404";}public static String getResponseHeader200(String context){return "HTTP/1.1 200 \r\n"+"Content-Type:text/html; charset=utf-8 \r\n"+"\r\n" + context;}
}

之后通过bufferoutputStream的write方法将数据返回给前端,注意发送后需要进行刷新

import com.qcby.ResponseUtil;
import java.io.BufferedOutputStream;
import java.io.IOException;import java.net.Socket;
import java.nio.charset.StandardCharsets;public class HttpServletResponse {Socket socket;public HttpServletResponse(Socket socket){this.socket = socket;}public void write(String s) throws IOException {BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());s = ResponseUtil.getResponseHeader200(s);outputStream.write(s.getBytes(StandardCharsets.UTF_8));outputStream.flush();outputStream.close();}
}

tomcat的整体流程如上,现在测试一下接收前端数据以及向前端返回数据信息:

http://www.dtcms.com/wzjs/307585.html

相关文章:

  • 做网站推广的联系方式保定seo网络推广
  • 山东淄博网站建设的公司关键词推广优化外包
  • 资海网站建设2345浏览器网站进入
  • 求推荐软件毕设代做靠谱网站内容营销策略
  • 自己的网站怎么做模板2023最近的新闻大事10条
  • 哪里找需要网站建设的市场营销咨询
  • 给个能看的网站企业网站的基本功能
  • 网络编程技术基础win7优化大师官方网站
  • 做pc端网站流程怎么开通百度推广账号
  • 织梦网站自动跳转手机网站百度知道网址
  • 长沙网页制作企业南京百度seo公司
  • 千户微建站平台搜索引擎网址有哪些
  • 动地科技登录网站软文写作经验是什么
  • 广昌网站建设百度平台客服
  • 团购网站APP怎么做搜索引擎有哪几个网站
  • 做网站的公司有前途吗网站策划是干什么的
  • 网站开发规划书全球搜钻
  • 做网站公司推荐微信视频号小店
  • 产品推广网站模板免费广告投放平台
  • 做公司网站建设价格低浏览器下载安装
  • 小程序制作页面教程网站优化推广方案
  • 深圳网站制作公司讯息南京seo排名收费
  • 宝鸡网站开发小红书seo是什么
  • 建设网站的申请信用卡分期付款一键搭建网站
  • 邵阳网站制作chrome下载
  • 电子商务网站开发是指百度我的订单app
  • 网站开发需求文档网络营销十大成功案例
  • 什么网站可以找到手工活做百度网址入口
  • 个人网站做多久有效果企业管理培训
  • 建立学校网站热狗seo顾问