WebSocket Day 01:入门案例

前言

欢迎来到WebSocket入门案例系列的第一天!在今天的博客中,我们将一起探索WebSocket的基础知识和使用方法。本系列将以一个简单的入门案例为基础,带领您逐步了解WebSocket的原理和用法。

一、什么是 WebSocket ?

WebSocket是一种在Web应用程序中实现实时双向通信的协议。它提供了一种持久连接,允许服务器主动向客户端推送数据,而不需要客户端发起请求。

传统的Web应用程序使用HTTP协议进行通信,这种通信方式是基于请求-响应模式的。客户端发送请求给服务器,服务器响应请求并返回相应的数据。但是这种方式存在一些限制,特别是对于实时性要求较高的应用场景,如聊天室、股票行情等。

WebSocket通过引入新的协议,提供了一种更高效、更低延迟的通信方式。相对于HTTP,WebSocket具有以下特点:

  1. 双向通信:WebSocket允许客户端和服务器之间进行双向通信,服务器可以主动向客户端推送数据,而不仅仅是响应客户端的请求。这使得实时性要求较高的应用程序能够更加高效地进行数据传输。

  2. 持久连接:WebSocket在建立连接后,保持持久的连接状态,而不需要每次通信都重新建立连接。这消除了每次请求建立连接和断开连接的开销,减少了网络流量和延迟。

  3. 低开销:相对于传统的HTTP请求-响应模式,WebSocket协议的数据帧头部较小,有效减少了通信过程中的数据开销。此外,由于使用持久连接,减少了连接建立和断开的开销。

  4. 兼容性:WebSocket协议基于TCP协议,通过HTTP/HTTPS进行握手协商,并在握手成功后升级为WebSocket连接。由于握手过程使用标准的HTTP/HTTPS协议,因此WebSocket可以通过大多数防火墙和代理服务器。

WebSocket在现代Web应用程序中被广泛应用,特别是对于需要实时通信和即时更新的应用场景。它为开发者提供了一种更加便捷、高效的方式来构建实时性强的Web应用程序。无论是聊天应用、实时博客评论、多人协作工具还是股票行情等都可以借助WebSocket实现更好的用户体验和数据交互。

二、为什么要使用 WebSocket 

WebSocket作为一种实现实时双向通信的协议,具有以下优点,这也是为什么要使用WebSocket的原因:

  1. 实时双向通信:传统的Web应用程序都是基于HTTP协议进行请求和响应的,无法实现实时双向通信。而WebSocket协议可以在客户端和服务器之间建立持久连接,实现实时双向通信,从而满足实时性比较强的应用场景。

  2. 低延迟:与HTTP协议相比,WebSocket协议的数据帧头部较小,有效减少了通信过程中的数据开销。由于使用持久连接,减少了连接建立和断开的开销,降低了延迟,提高了应用程序的响应速度和用户体验。

  3. 更好的扩展性:WebSocket协议采用标准的TCP协议,通过HTTP/HTTPS进行握手协商,并在握手成功后升级为WebSocket连接。由于握手过程使用标准的HTTP/HTTPS协议,WebSocket可以通过大多数防火墙和代理服务器。这使得应用程序更容易部署和扩展。

  4. 更低的网络流量:由于WebSocket协议使用二进制帧传输数据,相对于HTTP协议使用文本格式传输数据,WebSocket可以减少网络流量,提高应用程序的效率和性能。

总之,WebSocket协议提供了一种更高效、更低延迟、更实时、更灵活的通信方式,使得实时性较强的应用场景(如聊天室、在线游戏、多人协作工具等)更容易实现。如果您需要构建这些类型的应用程序,那么WebSocket将是您不错的选择。

三、实现一个单的 Hello WebSocket

1、新建项目,结构如下

2、导入依赖
<!-- websocket 依赖 --><dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.1</version><scope>provided</scope></dependency><!-- 打印日志 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.3.8</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency>

 下面是每个依赖项的作用:

  1. javax.websocket-api:这是一个Java API,用于支持WebSocket通信协议。WebSocket允许在客户端和服务器之间进行双向通信,实时地发送消息和数据。这个依赖项提供了WebSocket的核心接口和类。

  2. logback-classic:这是一个Java日志框架,用于在应用程序中记录和输出日志信息。logback-classic是logback框架的核心组件,它提供了强大的日志记录功能和灵活的配置选项。

  3. lombok:这是一个Java库,通过注解自动化简化了Java代码的编写。使用lombok可以减少样板代码,例如自动生成getter、setter、构造函数等。它提供了一些注解来简化代码的编写和维护,提高开发效率。

3、 编写 controller 类
@ServerEndpoint("/connect")
@Slf4j
public class WebSocketServer {/*** 打开连接的方法,当有一个客户端连接服务端的时候* 这个方法就会调用一次** @OnOpen注解:表示连接**/@OnOpenpublic void onOpen(){log.info("客户端已连接" );}/*** 客户端发送消息的方法*/@OnMessagepublic void onMessage(String message,Session session) throws IOException {log.info("消息:" + message);// 向当前客户端发送一个消息session.getBasicRemote().sendText(message);}/*** 当客户端断开连接后调用此方法*/@OnClosepublic void onClose(Session session){log.info("客户端已断开连接");}}

 在给出每个注解的用途之前,需要说明这段代码是Java中使用WebSocket的示例代码,使用了javax.websocket包提供的注解。

  1. @ServerEndpoint("/connect"):

    • 作用:将Java类标记为WebSocket服务器端点。
    • 解释:这个注解用于标识一个类是WebSocket的服务器端点,指定了客户端连接的URL路径。在上述示例中,客户端需要通过连接至"/connect"路径来与该服务器端点进行通信。
  2. @OnOpen:

    • 作用:定义打开连接时调用的方法。
    • 解释:当有客户端连接到WebSocket服务器端点时,被该注解标记的方法将会被调用。在示例中,onOpen()方法在客户端连接成功后执行,并打印出连接成功的消息。
  3. @OnMessage:

    • 作用:定义接收客户端消息时调用的方法。
    • 解释:当WebSocket服务器端点接收到客户端发送的消息时,被该注解标记的方法将会被调用。在示例中,onMessage()方法接收两个参数:String类型的message表示接收到的消息内容,Session类型的session表示与该客户端的会话。该方法在接收到消息后,会将消息原样发送回客户端。
  4. @OnClose:

    • 作用:定义客户端断开连接时调用的方法。
    • 解释:当与WebSocket服务器端点建立连接的客户端断开连接时,被该注解标记的方法将会被调用。在示例中,onClose()方法接收一个参数:Session类型的session,表示与断开连接的客户端的会话。该方法在客户端断开连接后执行,并打印出断开连接的消息。

这些注解是Java WebSocket API提供的一部分,通过使用这些注解,可以方便地定义WebSocket服务器端点的行为,包括连接建立、消息接收和断开连接等操作。

这个类是一个示例的WebSocket服务器端点类,用于处理客户端与服务器之间的WebSocket通信。主要功能如下:

  1. 打开连接:当有客户端连接到WebSocket服务器端点时,会调用onOpen()方法,并打印出连接成功的消息。

  2. 接收消息:当WebSocket服务器端点接收到客户端发送的消息时,会调用onMessage()方法,并打印出接收到的消息。同时,该方法会将接收到的消息原样发送回客户端。

  3. 断开连接:当与WebSocket服务器端点建立连接的客户端断开连接时,会调用onClose()方法,并打印出断开连接的消息。

这个类是使用了Java WebSocket API提供的注解来定义WebSocket服务器端点的行为。通过这些注解,可以方便地处理WebSocket的连接、消息接收和断开连接等操作。

4、编写一个 html 页面接收数据
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>websocket 客户端</h1><script>// 构建 websocket 的实例,连接后台 server 的请求地址// websocket 在第一次请求时使用 http 协议在连接服务器,告诉服务器// 接下来要使用 websocket 进行通信,此时服务器将进行协议升级,会在// http 的请求头中带有 upgrade:websocket 的头信息var webSocket = new WebSocket("ws://localhost:8080/connect");// onopen 方法webSocket.onopen = function () {// 发送一个消息webSocket.send("hello websocket");}// onmessage 方法,接受服务端发送的信息webSocket.onmessage = function (event) {alert("服务器的消息:" + event.data);}// onclose 方法webSocket.onclose = function () {alert("已断开连接");}</script></body>
</html>

这段代码是一个简单的WebSocket客户端示例,用于与WebSocket服务器进行通信。它的作用是:

  1. 创建WebSocket实例:通过var webSocket = new WebSocket("ws://localhost:8080/connect");语句创建了一个WebSocket实例,并指定了连接的服务器地址。

  2. 连接建立:当WebSocket连接成功建立时,会自动触发onopen事件处理函数,其中的webSocket.onopen定义了连接建立时的操作。在示例中,onopen函数中发送了一条消息webSocket.send("hello websocket");到服务器。

  3. 接收消息:当WebSocket客户端接收到来自服务器端的消息时,会触发onmessage事件处理函数,其中的webSocket.onmessage定义了接收消息时的操作。在示例中,当接收到消息时,会通过弹窗的方式显示服务器端发送的消息。

  4. 断开连接:当WebSocket连接关闭时,会触发onclose事件处理函数,其中的webSocket.onclose定义了连接关闭时的操作。在示例中,当连接关闭时,会通过弹窗的方式提示连接已断开。

这段代码展示了一个最基本的WebSocket客户端的工作流程,包括连接建立、消息发送和接收、连接断开等操作。您可以将其用于与WebSocket服务器进行实时通信,实现双向数据传输的功能。根据具体需求,您可以根据这个示例进行定制和扩展,添加更多的业务逻辑和交互功能。

 5、运行效果

我们在前端接收到了后台发送来的信息,在后台我们也接受到前端发送的信息,这就是一个简单的多对多的群聊了。

四、实现多人群聊

1、编写 controller 

@ServerEndpoint("/connect")
@Slf4j
public class WebSocketServer {/*** 用户列表*/private static final List<Session> users = new ArrayList<>();/*** 打开连接的方法,当有一个客户端连接服务端的时候* 这个方法就会调用一次** @OnOpen注解:表示连接** @param session 表示一个 websocket 客户端的连接会话*                每一个客户端连接就会创建一个 session 会话*/@OnOpenpublic void onOpen(Session session){log.info("客户端已连接" );// 将 session 添加到用户列表中users.add(session);}/*** 客户端发送消息的方法*/@OnMessagepublic void onMessage(String message,Session session) throws IOException {log.info("消息:" + message);// 获取当前时间String formattedTime = new SimpleDateFormat("HH:mm:ss").format(new Date());// 向当前客户端发送一个消息,包含发送时间String messageWithTime = "[" + formattedTime + "] " + message;for (Session user : users) {// 群发信息user.getBasicRemote().sendText(messageWithTime);}}/*** 当客户端断开连接后调用此方法*/@OnClosepublic void onClose(Session session){log.info("客户端已断开连接");// 用户离线users.remove(session);}}

 解释一下每一行代码的意思:

1)、定义了一个静态的会话列表users,用于存储所有连接到WebSocket服务端的客户端Session对象。
private static final List<Session> users = new ArrayList<>();
2)、使用@OnOpen注解声明一个方法,该方法用于处理WebSocket客户端连接到服务器后的操作。当有一个新客户端连接到服务器时,该方法会被自动调用。在该方法中,首先记录下客户端连接成功的日志信息,然后将客户端的Session对象保存到静态会话列表中。
@OnOpen
public void onOpen(Session session){log.info("客户端已连接" );// 将 session 添加到用户列表中users.add(session);
}
3)、使用@OnMessage注解声明一个方法,该方法用于处理WebSocket客户端发送消息的操作。当客户端向服务器发送消息时,该方法会被自动调用,并传入消息内容和对应的Session对象。在该方法中,首先记录下客户端发送的消息内容,然后获取当前时间,并将时间和消息内容拼接为一个新的字符串。最后,遍历所有连接到服务器的客户端(即静态会话列表users),并将消息广播给所有客户端。
@OnMessage
public void onMessage(String message,Session session) throws IOException {log.info("消息:" + message);// 向当前客户端发送一个消息
//         session.getBasicRemote().sendText(message);// 获取当前时间String formattedTime = new SimpleDateFormat("HH:mm:ss").format(new Date());// 向当前客户端发送一个消息,包含发送时间String messageWithTime = "[" + formattedTime + "] " + message;for (Session user : users) {// 群发信息user.getBasicRemote().sendText(messageWithTime);}}
4)使用@OnClose注解声明一个方法,该方法用于处理WebSocket客户端断开连接的操作。当有一个客户端与服务器断开连接时,该方法会被自动调用,并传入断开连接的Session对象。在该方法中,首先记录下客户端断开连接的日志信息,然后将与断开连接的客户端对应的Session对象从静态会话列表中移除。
@OnClose
public void onClose(Session session){log.info("客户端已断开连接");// 用户离线users.remove(session);
}
2、编写一个页面发送信息
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/JQuery文件.txt.js"></script>
</head>
<body>
<h1>聊天室</h1>
<div id="msg"></div>
<input id="message" type="text"/>
<input type="button" value="发送"/>
<script>//创建websocket对象let ws = new WebSocket("ws://localhost:8080/connect");//接收服务端的消息ws.onmessage = function(event){let message = event.data;//将消息放入聊天框$('#msg').append(message + '<br>');}$(function(){$(':button').on('click',function(){//获取文本消息let msg = $('#message').val();//发送消息ws.send(msg);//清空发送框$('#message').val('');});})
</script></body>
</html>

这段代码是一个简单的HTML页面,它实现了一个基本的聊天室功能。具体功能如下:

  1. 在页面上显示一个标题为"聊天室"的大标题。
  2. 有一个用于显示聊天消息的<div>元素,它的id属性为"msg"。
  3. 有一个<input>元素,用于输入要发送的消息,它的id属性为"message"。
  4. 有一个<input>按钮,用于发送消息,按钮上显示"发送"。
  5. 使用JavaScript和jQuery库来处理页面上的交互逻辑。

在脚本部分,代码实现了以下功能:

  1. 创建了一个WebSocket对象,通过指定WebSocket服务器的URL来建立与服务器的连接。在这个例子中,服务器的URL是"ws://localhost:8080/connect"。
  2. 设置了一个事件处理程序(ws.onmessage),当接收到来自服务器的消息时,会触发该事件,并将消息显示在聊天框中。
  3. 使用jQuery库,在页面加载完成后,绑定了按钮的点击事件处理程序。当按钮被点击时,获取输入框中的文本消息,并通过WebSocket发送给服务器。然后清空输入框,以便输入下一条消息。

通过将这段代码部署到一个能够处理WebSocket协议的服务器上,你可以创建一个简单的聊天室页面,用户可以在其中实时地发送和接收消息。当用户在输入框中输入消息并点击发送按钮时,消息将通过WebSocket发送给服务器,在服务器上处理后,会将消息广播给所有连接的客户端,以便显示在聊天框中。这样就实现了简单的聊天室功能。 

3、运行效果

 五、使用局域网 IP 地址实现多人群聊

1、使用命令查看 IP 地址

win + r 打开命令提示符,输入 cmd 回车进入。在控制面板输出 : ipconfig 回车即可查询到自己本机的 IP.

2、在 client.html 页面更改 url

只需要把 localhost 换成自己本机的 IP 地址即可。

3、运行效果

改完 url 地址后,我们在浏览器就不能使用 localhost:8080 去访问了。

使用 IP 地址后的访问路径为:http://本机IP地址:8080/chat.html 

4、什么是局域网?

局域网通常用于连接位于同一地理位置的多台计算机和设备。

注意:我们使用的是局域网的 IP 地址去和同学聊天的,如果你们使用的是同一个网络就能够正常的访问这个路径去聊天,如果不在同一网络就不能。比如:教室、学校、家里的WIFI,都可以。

 六、总结

        本次案例,我们简单的讲解了实现聊天的功能。但是,这只是一个开头,我们要实现真正的聊天还有很多其他的功能要做,比如:登录,登录成功后获取用户的名称。我们这次聊天是不知道用户名的,只有时间和内容,那么在下一章节我将要讲解如何实现登录后实现聊天。

        

七、gitee 案例

地址:ch01 · qiuqiu/WebSocket-study - 码云 - 开源中国 (gitee.com)

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

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

相关文章

java版直播商城免费搭建平台规划及常见的营销模式+电商源码+小程序+三级分销+二次开发

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

web —— html

Web —— css基础 1. HTML2. 基本HTML结构3. HTML常用标签3.1 文本相关标签3.2 HTML图像标签3.3 HTML超链接标签3.4 HTML表&#xff0c;单3.4.1 HTML表格3.4.2 HTML表单&#xff0c;输入框&#xff08;多选框&#xff0c;单选框&#xff09;下拉框 3.5 HTML分区标签3.5.1 div标…

【Midjourney入门教程3】写好prompt常用的参数

文章目录 1、图片描述词&#xff08;图片链接&#xff09;文字描述词后缀参数2、权重划分3、后缀参数版本选择&#xff1a;--v版本风格&#xff1a;--style长宽比&#xff1a;--ar多样性: --c二次元化&#xff1a;--niji排除内容&#xff1a;--no--stylize--seed--tile、--q 4、…

实战-edusrc漏洞挖掘

0x01系统初探 通过fofa对大学进行搜索 fofa:host"edu.cn" &amp;&amp; status_code"200"在随意的翻阅查看时&#xff0c;发现访问xxx.edu.cn登录页面会优先访问登录后的页面&#xff0c;再跳转至登录页面。盲猜应该是前端校验&#xff0c;可以通过…

C++项目的一些环境配置

今天学习下OpenCV&#xff0c;环境配置顺便理一下&#xff1a; 1.用到外部的C文件要在&#xff1a;项目的属性页->VC目录->包含目录&#xff0c;添加相应的路径 2.用到外部的库文件需要在&#xff1a;项目的属性页->VC目录->库目录&#xff0c;添加相应的路径&…

Ps:色彩范围

Ps菜单&#xff1a;选择/色彩范围 Select/Color Range 色彩范围 Color Range是一个功能强大选择命令&#xff0c;不仅可以基于颜色进行选择&#xff0c;而且可以基于影调进行选择。不仅可以用来检测人脸选择肤色&#xff0c;也可用来选择超出印刷色域范围的区域。 在图层蒙版的…

七种事务传播行为,核心只有Required默认和required_new

事务的概念&#xff1a;当一个事务方法被另一个事务方法调用时&#xff0c;这个事务方法应该如何进行事务控制。 结论&#xff1a;一般情况下&#xff0c;你就用默认的把两个事务合并成一个事务&#xff0c;只有当写日志&#xff08;事物之间不互相影响&#xff09;的时候用req…

光学仿真 | 仿真推动以人类视觉感知为本的汽车显示设计

如果产品设计无法使终端用户产生共鸣&#xff0c;就不会存在卓越的工程设计。您可以设计一种结构坚固的方向盘&#xff0c;但如果它被放在错误的位置&#xff0c;就无法实现其用于转向的主要目的。 同样&#xff0c;在围绕人类视觉进行设计时&#xff0c;显示器其实无需具备尽…

【C/C++笔试练习】内联函数、哪些运算符不能重载、拷贝构造函数、const类型、函数重载、构造函数、空类的大小、井字棋、密码强度等级

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;内联函数&#xff08;2&#xff09;哪些运算符不能重载&#xff08;3&#xff09;拷贝构造函数&#xff08;4&#xff09;const类型&#xff08;5&#xff09;函数重载&#xff08;6&#xff09;构造函数&#xff08;7&a…

Xilinx DDR3 MIG系列——内存基本概念及原理

本节目录 一、内存简介 (1)内存基本存储原理 (2)内存频率 (3)DDR数据预取技术(Prefetch) (4)DDR3工作流程 (5)DDR3控制器的特点 二、内存基本参数 (1)物理Bank (2)逻辑Bank (3)内存芯片容量 (4)行激活命令—tRCD (5)列选通—CL (6)写入延迟—tDQSS (7)行预充电有效周期—tRP (8…

css 图片好玩的一个属性,添加滤镜

鼠标经过效果对比&#xff1a; 上图是改变了图片的饱和度&#xff0c;代码如下&#xff1a; .img-box .v-image:hover {filter: saturate(1.75); }其他滤镜说明如下图&#xff1a;

数字人IP为何成家电品牌年轻化营销黑马?

伴随着数字人概念的出现&#xff0c;家电品牌逐渐通过3D虚拟数字人定制&#xff0c;让数字人成为内容、变现一体的IP&#xff0c;形成一定影响力的品牌效应&#xff0c;利用长线内容沉淀粉丝&#xff0c;使品牌实现年轻化营销。 *图片源于网络 如近日在海尔智家旗下品牌发布会上…

网上书店项目

源码下载地址 支持&#xff1a;远程部署/安装/调试、讲解、二次开发/修改/定制 程序运行视频查看 管理员 图书管理 添加图书 删除图书(可批量删除) 修改图书 查看图书(分页查看) 图书上下架(可批量处理) 图书推荐&#xff08;新品推荐、精品推荐&#xff0c;可批量处理&#…

灵活调整宣传策略,媒体发稿和新闻发布的优势所在

企业在当今信息爆炸的时代&#xff0c;要想在市场竞争中脱颖而出&#xff0c;提高公信力是至关重要的。而媒体发稿和新闻发布是提升企业公信力的重要手段之一。下面将从门户网站的权威展示、搜索引擎排名的提升、内容的持续稳定有效性、内容的可改性以及协助增加网站流量等方面…

【owt】p2p client mfc 工程梳理

1年前构建的,已经搞不清楚了。所以梳理下,争取能用较新的webrtc版本做测试。最早肯定用这个测试跑通过 【owt】p2p Signaling Server 运行、与OWT-P2P-MFC 交互过程及信令分析官方的mfc客户端 估计是构造了多个不同的webrc版本的客户端

Git介绍及使用

目录 一、Git 的基本概念 1. 仓库&#xff08;Repository&#xff09;: 仓库是存储代码的地方。可以通过 命令将本地文件夹初始化为 Git 仓库&#xff0c;并使用 命令从远程仓库克隆到本地 2. 分支&#xff08;Branch&#xff09;: 分支是指从主分支上创建出来的一个分支&…

云计算实战项目之---学之思在线考试系统

简介&#xff1a; 学之思开源考试系统是一款 java vue 的前后端分离的考试系统。主要优点是开发、部署简单快捷、界面设计友好、代码结构清晰。支持web端和微信小程序&#xff0c;能覆盖到pc机和手机等设备。 支持多种部署方式&#xff1a;集成部署、前后端分离部署、docker部…

如何在Python爬虫中使用IP代理以避免反爬虫机制

目录 前言 一、IP代理的使用 1. 什么是IP代理&#xff1f; 2. 如何获取IP代理&#xff1f; 3. 如何使用IP代理&#xff1f; 4. 如何避免IP代理失效&#xff1f; 5. 代理IP的匿名性 二、代码示例 总结 前言 在进行爬虫时&#xff0c;我们很容易会遇到反爬虫机制。网站…

Vue3:解决基地址不同 数据交互http与https跨域问题

配置公共管理的api文件和vue.config.js可以解决跨域问题。一个项目对接不同的基地址和接口同理。 api export default {//接口基地址Millia: process.env.NODE_ENV development ? location.protocol // location.host /milliaApi : http://xx.xxx.xxxx/index.php/,Milli…

django+drf+vue 简单系统搭建 (1) - django创建项目

本系列文章为了记录自己第一个系统生成过程&#xff0c;主要使用django,drf,vue。本人非专业人士&#xff0c;此文只为记录学习&#xff0c;若有部分描述不够准确的地方&#xff0c;烦请指正。 建立这个系统的原因是因为&#xff0c;在生活中&#xff0c;很多觉得可以一两行代码…