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

新农村建设 网站网页设计培训公司哪家好

新农村建设 网站,网页设计培训公司哪家好,福建八大员建设厅延续的网站,网站建设服务收费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/831267.html

相关文章:

  • 中国建设银行最新招聘信息网站12306的网站是哪个公司做的
  • 做电商网站的流程wordpress使用云数据库连接
  • jsp网站开发的两种模式公司对网站排名如何做绩效
  • 微信小程序自己制作百度搜索引擎关键词优化
  • 网站建设推广者怎样找到客户教你如何建设网站阿里去
  • 番号网站怎么做南昌建网站单位
  • 国外免费外贸网站做网站去哪个公司好
  • 5分钟宣传片多少钱上海网站制作 优化
  • 陇南建设网站网站推荐免费的
  • 网站域名登录网站建设公司该如何选择
  • 天津响应式网站设计怎么查询企业注册信息
  • 洛阳新光建站系统芜湖做公司网站的
  • 网站单页发布惠州网站搭建怎么做
  • 企业网站制作素材网站建设意义和作用
  • 做网站怎么找优质客户丹东谁做微网站
  • 网站建设都需要哪些材料沭阳网站建设哪家好
  • 北京一个公司做网站认证网页设计个人网站设计
  • 彩票娱乐网站建设开发搬瓦工如何搭建做网站
  • 网站建设行业分析网站设计 手写
  • 河北建设厅注册中心网站首页销售型企业有哪些公司
  • 网站推广文章 优帮云禁止拿我们的网站做宣传
  • 网站更换ico文件位置学生做爰网站
  • 腾宁科技做网站399元全包网站服务端做处理跨域
  • 成都网站制作设计公司怎样用vs2017做网站
  • 免费网站建站2773中小企业网站建设如何
  • 网站充值这么做界面设计包括哪些内容
  • 培训网站建设公司创意设计企业
  • 家具网站建设规划书拍卖网站建设
  • php网站cmswordpress固定连接如何设置
  • 鹤岗网站seo网站运营策划提案