WebSocket实现聊天

news2024/11/23 11:43:29

基于webSocket通信的库主要有 socket.io,SockJS,这次用的是 SockJS。

这里我们使用sockjs-client、stomjs这两个模块,要实现webSocket通信,需要后台配合,也使用相应的模块。

WebSocket

1、http:http超文本传输协议,http有1.0、1.1、 2.0几个版本,从http1.1起,默认都开启了Keep-Alive,保持连接持续性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输http数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接,这样就降低了资源的消耗优化性能,但是Keep-Alive也是有时间限制的,还有一个客户端只能主动发起请求才能获取返回数据,并不能主动接收后台推送的数据,websocket便应运而生。

2、websocket:是 html5 新增加特性之一,目的是浏览器与服务端建立全双工的通信方式,解决 http 请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天、股票交易、游戏等对对实时性要求较高的行业领域。

http与websocket都是基于TCP(传输控制协议)的,websocket可以看做是对http协议的一个补充。

WebSocket协议提供了通过一个套接字实现全双工通信的功能。除了其他的功能之外,它能够实现Web浏览器和服务器之间的异步通信。全双工意味着服务器可以发送消息给浏览器,浏览器也可以发送消息给服务器。

3、SockJs:SockJS是一个JavaScript库,为了应对许多浏览器不支持WebSocket协议的问题,设计了备选SockJs。SockJS 是 WebSocket 技术的一种模拟。SockJS会尽可能对应 WebSocket API,但如果WebSocket 技术不可用的话,会自动降为轮询的方式。

SockJS会优先选择WebSocket进行连接,但是当服务器或客户端不支持WebSocket时,会自动在 XHR流、XDR流、iFrame事件源、iFrame HTML文件、XHR轮询、XDR轮询、iFrame XHR轮询、JSONP轮询 这几个方案中择优进行连接。

4、Stompjs:STOMP—— Simple Text Oriented Message Protocol——面向消息的简单文本协议。SockJS 为 WebSocket 提供了 备选方案。但无论哪种场景,对于实际应用来说,这种通信形式层级过低。

STOMP协议,来为浏览器 和 server 间的 通信增加适当的消息语义。

5、WebSocket、SockJs、STOMP三者关系

简而言之,WebSocket 是底层协议,SockJS 是WebSocket 的备选方案,也是底层协议,而 STOMP 是基于 WebSocket(SockJS)的上层协议。

(1)HTTP协议解决了 web 浏览器发起请求以及 web 服务器响应请求的细节,假设 HTTP 协议 并不存在,只能使用 TCP 套接字来 编写 web 应用,那将是一件非常痛苦的事情。

(2)直接使用 WebSocket(SockJS) 就很类似于 使用 TCP 套接字来编写 web 应用,因为没有高层协议,就需要我们定义应用间所发送消息的语义,还需要确保连接的两端都能遵循这些语义;

(3)同HTTP在TCP 套接字上添加请求-响应模型层一样,STOMP在WebSocket 之上提供了一个基于帧的线路格式层,用来定义消息语义;

SockJS

WebSocket是一个相对比较新的规范,在Web浏览器和应用服务器上没有得到一致的支持。所以我们需要一种WebSocket的备选方案,而这恰恰是SockJS所擅长的。

SockJS是WebSocket技术的一种模拟,在表面上,它尽可能对应WebSocket API,但是在底层非常智能。如果WebSocket技术不可用的话,就会选择另外的通信方式。

使用SockJS

只需加上withSockJS()方法就能声明我们想要使用SockJS功能,如果WebSocket不可用的话,SockJS的备用方案就会发挥作用。

同时需要注意的是,如果我们不是使用 SockJS,那么后端代码就只需要把这个 withSockJS() 去掉即可,那么就会采用 websocket 来连接。

sockjs-client

sockjs-client是从SockJS中分离出来的用于客户端使用的通信模块,所以我们就直接来看看SockJS。

SockJS是一个浏览器的JavaScript库,它提供了一个类似于网络的对象,SockJS提供了一个连贯的、跨浏览器的JavaScriptAPI,它在浏览器和Web服务器之间创建了一个低延迟、全双工、跨域通信通道。

你可能会问,我为什么不直接用原生的WebSocket而要使用SockJS呢?

这得益于SockJS的一大特性,一些浏览器中缺少对WebSocket的支持,因此回退选项是必要的,而Spring框架提供了基于SockJS协议的透明的回退选项。SockJS提供了浏览器兼容性,优先使用原生的WebSocket,如果某个浏览器不支持WebSocket,SockJS会自动降级为轮询。

stomjs

STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的简单文本协议,WebSocket是一个消息架构,不强制使用任何特定的消息协议,它依赖于应用层解释消息的含义。

与HTTP不同,WebSocket是处在TCP上非常薄的一层,会将字节流转化为文本/二进制消息,因此,对于实际应用来说,WebSocket的通信形式层级过低,因此可以在 WebSocket 之上使用STOMP协议,来为浏览器 和 server间的通信增加适当的消息语义。

STOMP与WebSocket 的关系

HTTP协议解决了web浏览器发起请求以及web服务器响应请求的细节,假设HTTP协议不存在,只能使用TCP套接字来编写web应用,你可能认为这是一件疯狂的事情

直接使用WebSocket(SockJS)就很类似于使用TCP套接字来编写web应用,因为没有高层协议,就需要我们定义应用间发送消息的语义,还需要确保连接的两端都能遵循这些语义。

同HTTP在TCP套接字上添加请求-响应模型层一样,STOMP在WebSocket之上提供了一个基于帧的线路格式层,用来定义消息语义。

前端代码实现:

先安装 sockjs-client 和 stompjs

npm install sockjs-client
npm install stompjs
<script>
  import SockJS from 'sockjs-client'
  import Stomp from 'stompjs'
  export default {
    ......
    methods: {
      ......
    // 连接后台
      connection () {
        let that = this
        // 建立连接对象
        let sockUrl = '/api/***?token=' + this.token.substring(7) + '&abc=' + this.$route.params.id
        let socket = new SockJS(sockUrl)
        // 获取STOMP子协议的客户端对象
        this.stompClient = Stomp.over(socket)
        // 定义客户端的认证信息,按需求配置
        let headers = {
          Authorization: ''
        }
        // 向服务器发起websocket连接
        this.stompClient.connect(headers, (res) => {
          // 订阅服务端提供的某个topic
          this.stompClient.subscribe('/topic/***/' + this.$route.params.id, (frame) => {
            that.addBarage(JSON.parse(frame.body))
          })
          that.sentFirst()
        }, (err) => {
          console.log('失败:' + err)
        })
        this.stompClient.debug = null
      },
      // 断开连接
      disconnect () {
        if (this.stompClient) {
          this.stompClient.disconnect()
        }
      },
      // 初始化websocket
      initWebSocket () {
        this.connection()
        let that = this
        // 断开重连机制,尝试发送消息,捕获异常发生时重连
        this.timer = setInterval(() => {
          try {
            that.stompClient.send('connect-test')
          } catch (err) {
            console.log('断线了: ' + err)
            that.connection()
          }
        }, 5000)
      },
      // 用户加入发送弹幕
      keyDown (e) {
        if (e.keyCode === 13) {
          if (e.preventDefault) {
            e.preventDefault()
          } else {
            window.event.returnValue = false
          }
          this.sentBarrage()
        }
      }
    },
    mounted () {this.initWebSocket()
    },
    beforeDestroy () {
      if (this.player) {
        this.player.dispose()
        this.player = null
      }
      // 页面离开时断开连接,清除定时器
      this.disconnect()
      clearInterval(this.timer)
    }
  }
</script>
JavaScript客户端代码

要在客户端使用SockJS,需要确保加载了SockJS客户端库。

<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>

除了加载SockJS客户端库外,要使用SockJS只需要修改两行代码即可:

var url = 'marco';
var sock = new SockJS(url);
//SockJS所处理的URL是http://或https://,不再是ws://和wss://

运行效果一样,但是客户端–服务器之间通信的方式却有了很大的变化。

使用STOMP消息

STOMP在WebSocket之上提供了一个基于帧的线路格式层,用来定义消息的语义。

STOMP帧由命令、一个或多个头信息以及负载所组成。

STOMP命令是SEND,表明会发送一些内容。紧接着是两个头信息:一个用来表示消息要发送到哪里的目的地,另外一个则包含了负载的大小。然后,紧接着是一个空行,STOMP帧的最后是负载内容。

STOMP帧中最有意思的是destination头信息了。它表明STOMP是一个消息协议。消息会发布到某个目的地,这个目的地实际上可能真的有消息代理作为支撑。另一方面,消息处理器也可以监听这些目的地,接收所发送过来的消息。

启用STOMP消息功能

WebSocketStompConfig 重载了registerStompEndpoints() 方法,将/marcopolo注册为STOMP端点。

这个路径与之前接收和发送消息的目的地路径有所不同。这是一个端点,客户端在订阅或发布消息到目的地前,要连接该端点。

WebSocketStompConfig还通过重载configureMessageBroker() 方法配置了一个简单的消息代理。这个方法是可选的,如果不重载它的话,将会自动配置一个简单的内存消息代理,用它来处理以“/topic”为前缀的消息。

处理来自客户端的STOMP消息

<script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>
<script>
var url = 'http://'+window.location.host+'/yds/marcopolo';
var sock = new SockJS(url);  //创建SockJS连接。
var stomp = Stomp.over(sock);//创建STOMP客户端实例。实际上封装了SockJS,这样就能在WebSocket连接上发送STOMP消息。
var payload = JSON.stringify({'message':'Marco!'});
stomp.connect('guest','guest',function(frame){
  stomp.send("/app/marco",{},payload);
  stomp.subscribe('/app/subscribe', function(message){

  });
});
</script> 

发送消息到客户端

如果你想要在接收消息的时候,同时在响应中发送一条消息,那么需要做的仅仅是将内容返回就可以了。

stomp.subscribe('/topic/marco', function(message){    // 订阅后将会接收到消息。
});

为目标用户发送消息

image.png

为指定用户发送消息

stomp.subscribe('/users/1/message', function(message){ 
});

客户端接收一对一消息的主题是"/users/“+usersId+”/message",这里的用户Id可以是一个普通字符串,只要每个客户端都使用自己的Id并且服务器端知道每个用户的Id就行了。

具体前端如何实现

创建STOMP客户端

在web浏览器中使用普通的Web Socket

STOMP javascript 客户端会使用 ws://的URL与STOMP 服务端进行交互。

为了创建一个STOMP客户端 js 对象,你需要使用 Stomp.client(url),而这个URL连接着服务端的WebSocket的代理

var url = "ws://localhost:61614/stomp";
var client = Stomp.client(url);

Stomp.client(url, protocols)也可以用来覆盖默认的subprotocols。第二个参数可以是一个字符串或一个字符串数组去指定多个subprotocols。

在web浏览器中使用定制的WebSocket

浏览器提供了不同的WebSocket的协议,一些老的浏览器不支持WebSocket的脚本或者使用别的名字。默认下,stomp.js会使用浏览器原生的WebSocket class去创建WebSocket。

但是利用 Stomp.over(ws)这个方法可以使用其他类型的 WebSockets,这个方法得到一个满足WebSocket定义的对象。例如,可以使用由 SockJS实现的Websocket。

如果使用原生的 Websocket 就使用 Stomp.client(url),如果需要使用其他类型的 Websocket(例如由SockJS包装的Websocket)就使用Stomp.over(ws)。除了初始化有差别,Stomp API 在这两种方式下是相同的。

在 node.js程序中

通过stompjs npm package同样也可以在node.js程序中使用这个库。

// 安装
npm install stompjs

在node.js中,require这个模块:var Stomp = require(‘stompjs’);

为了与建立在TCP socket的STOMP-broker连接,使用Stomp.overTCP(host, port)方法。

var client = Stomp.overTCP('localhost', 61613);

为了与建立在Web Socket的STOMP broker连接,使用Stomp.overWS(url)方法。

var client = Stomp.overWS('ws://localhost:61614/stomp');

除了初始化不同,无论是浏览器还是node.js环境下,Stomp API都是相同的。

连接服务端

一旦 Stomp 客户端建立了,必须调用它的 connect()方法去连接 Stomp 服务端进行验证。这个方法需要两个参数,用户的登录和密码凭证。这种情况下,客户端会使用Websocket打开连接,并发送一个 CONNECT frame。

这个连接是异步进行的:你不能保证当这个方法返回时是有效连接的。为了知道连接的结果,你需要一个回调函数。

var connect_callback = function() {
    // called back after the client is connected and authenticated to the STOMP server
};

但是如果连接失败会发生什么呢?

connect()方法接受一个可选的参数(error_callback),当客户端不能连接上服务端时,这个回调函数error_callback会被调用,该函数的参数为对应的错误对象。

var error_callback = function(error) {
    // display the error's message header:
    alert(error.headers.message);
};

在大多数情况下,connect()方法可接受不同数量的参数来提供简单的API:

client.connect(login, passcode, connectCallback);
client.connect(login, passcode, connectCallback, errorCallback);
client.connect(login, passcode, connectCallback, errorCallback, host);

login和passcode是strings,connectCallback和errorCallback则是functions。(有些brokers(代理)还需要传递一个host(String类型)参数。)

如果你需要附加一个headers头部,connect方法还接受其他两种形式的参数:

client.connect(headers, connectCallback);
client.connect(headers, connectCallback, errorCallback);

header是map形式,connectCallback和errorCallback为functions。

需要注意:如果你使用上述这种方式,你需要自行在headers添加login、passcode(甚至host):

var headers = {
    login: 'mylogin',
    passcode: 'mypasscode',
    // additional header
    'client-id': 'my-client-id'
};
client.connect(headers, connectCallback);

断开连接时,调用disconnect方法,这个方法也是异步的,当断开成功后会接收一个额外的回调函数的参数。如下所示。

client.disconnect(function() {
    alert("See you next time!");
};

当客户端与服务端断开连接,就不会再发送或接收消息了。

Heart-beating

如果STOMP broker(代理)接收STOMP 1.1版本的帧,heart-beating是默认启用的。

heart-beating也就是频率,incoming是接收频率,outgoing是发送频率。通过改变incoming和outgoing可以更改客户端的heart-beating(默认为10000ms):

client.heartbeat.outgoing = 20000; 
// client will send heartbeats every 20000ms
client.heartbeat.incoming = 0;
// client does not want to receive heartbeats
// from the server

heart-beating是利用window.setInterval()去规律地发送heart-beats或者检查服务端的heart-beats。

发送消息

当客户端与服务端连接成功后,可以调用 send()来发送STOMP消息。这个方法必须有一个参数,用来描述对应的STOMP的目的地。另外可以有两个可选的参数:headers,object类型包含额外的信息头部;body,一个String类型的参数。

client.send("/queue/test", {priority: 9}, "Hello, STOMP");
// client会发送一个STOMP发送帧给/queue/test,
这个帧包含一个设置了priority为9的header和内容为“Hello, STOMP”的body。

client.send(destination, {}, body);

如果你想发送一个有body的信息,也必须传递headers参数。如果没有headers需要传递,那么就传{}即可。

订阅(Subscribe)和接收(receive)消息

为了在浏览器中接收消息,STOMP客户端必须先订阅一个目的地 destination。

你可以使用subscribe()去订阅。这个方法有2个必需的参数:目的地(destination),回调函数(callback);还有一个可选的参数headers。其中destination是String类型,对应目的地,回调函数是伴随着一个参数的function类型。

var subscription = client.subscribe("/queue/test", callback);

subscribe()方法返回一个object,这个object包含一个id属性,对应这个这个客户端的订阅ID。

而unsubscribe()可以用来取消客户端对这个目的地destination的订阅。

默认情况下,如果没有在headers额外添加,这个库会默认构建一个独一无二的ID。在传递headers这个参数时,可以使用你自己的ID。

var mysubid = '...';
var subscription = client.subscribe(destination, callback, { id: mysubid });

这个客户端会向服务端发送一个STOMP订阅帧(SUBSCRIBE frame)并注册回调事件。每次服务端向客户端发送消息时,客户端都会轮流调用回调函数,参数为对应消息的STOMP帧对象(Frame object)。

subscribe()方法,接受一个可选的headers参数用来标识附加的头部。

var headers = {ack: 'client', 'selector': "location = 'Europe'"};
client.subscribe("/queue/test", message_callback, headers);

这个客户端指定了它会确认接收的信息,只接收符合这个selector : location = 'Europe’的消息。

如果想让客户端订阅多个目的地,你可以在接收所有信息的时候调用相同的回调函数:

onmessage = function(message) {
    // called every time the client receives a message
}
var sub1 = client.subscribe("queue/test", onmessage);
var sub2 = client.subscribe("queue/another", onmessage)

如果要中止接收消息,客户端可以在subscribe()返回的object对象调用unsubscribe()来结束接收。

var subscription = client.subscribe(...);
...
subscription.unsubscribe();

支持JSON

STOMP消息的body必须为字符串。如果你需要发送/接收JSON对象,你可以使用JSON.stringify()和JSON.parse()去转换JSON对象。

Acknowledgment(确认)

默认情况,在消息发送给客户端之前,服务端会自动确认(acknowledged)。

客户端可以选择通过订阅一个目的地时设置一个ack header为client或client-individual来处理消息确认。

在下面这个例子,客户端必须调用message.ack()来通知服务端它已经接收了消息。

var subscription = client.subscribe("/queue/test",
    function(message) {
        // do something with the message
        ...
        // and acknowledge it
        message.ack();
    },
    {ack: 'client'}
);

ack()接受headers参数用来附加确认消息。例如,将消息作为事务(transaction)的一部分,当要求接收消息时其实代理(broker)已经将ACK STOMP frame处理了。

var tx = client.begin();
message.ack({ transaction: tx.id, receipt: 'my-receipt' });
tx.commit();

nack()也可以用来通知STOMP 1.1.brokers(代理):客户端不能消费这个消息。与ack()方法的参数相同。

事务(Transactions)

可以在将消息的发送和确认接收放在一个事务中。

客户端调用自身的begin()方法就可以开始启动事务了,begin()有一个可选的参数transaction,一个唯一的可标识事务的字符串。如果没有传递这个参数,那么库会自动构建一个。这个方法会返回一个object。这个对象有一个id属性对应这个事务的ID,还有两个方法:

  • commit()提交事务
  • abort()中止事务

在一个事务中,客户端可以在发送/接受消息时指定transaction id来设置transaction。

// start the transaction
var tx = client.begin();
// send the message in a transaction
client.send("/queue/test", {transaction: tx.id}, "message in a transaction");
// commit the transaction to effectively send the message
tx.commit();

如果你在调用send()方法发送消息的时候忘记添加transction header,那么这不会称为事务的一部分,这个消息会直接发送,不会等到事务完成后才发送。

var txid = "unique_transaction_identifier";
// start the transaction
var tx = client.begin();
// oops! send the message outside the transaction
client.send("/queue/test", {}, "I thought I was in a transaction!");
tx.abort(); // Too late! the message has been sent

调试

有一些测试代码能有助于你知道库发送或接收的是什么,从而来调试程序。

客户端可以将其debug属性设置为一个函数,传递一个字符串参数去观察库所有的debug语句。默认情况,debug消息会被记录在在浏览器的控制台。

client.debug = function(str) {
    // append the debug log to a #debug div somewhere in the page using JQuery:
    $("#debug").append(str + "\n");
};

使用情况

1、var error_callback = function(error) {};第一次连接失败和连接后断开连接都会调用这个函数

2、关闭控制台调试数据:设置client.debug = null 就可以,stompjs会去检测debug是否是函数,不是函数就不会调用输出。

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

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

相关文章

War Robots可以使用5347的卡支付

很多小伙伴想使用War Robots&#xff0c;但是不知道怎么弄&#xff0c;方法比较可靠&#xff0c;亲测有效~~~ 可以使用Fomepay的5347的卡支付 卡片cvc就是卡密&#xff0c;在首页点击更多时可以查看

【ubuntu2004安装N卡驱动】

软硬件环境 硬件&#xff1a;联想notebook16&#xff0c;显卡4060laptop 软件&#xff1a; ubuntu20.04 驱动安装成功的版本&#xff1a;NVIDIA-Linux-x86_64-535.146.02.run 使用默认的驱动安装&#xff0c;没用原因如下 让手动安装。 手动安装 环境准备&#xff1a; sudo …

【shap】使用shap画图时colorbar颜色条不能正常显示

下面&#xff0c;我的shap值全是蓝色的&#xff0c;没有红色 &#xff08;注&#xff1a;蓝色是负贡献&#xff0c;红色是正贡献&#xff09; 参考上面的帖子&#xff0c;是matplotlib版本问题&#xff0c;我原来的版本是3.5.0&#xff0c;降级回3.4.3就正常了。

心律守护 基于机器学习的心脏病预测

心律守护 基于机器学习的心脏病预测 心律守护 基于机器学习的心脏病预测项目背景与意义项目数据与特征数据分析与预处理机器学习模型建立与评估结语 心律守护 基于机器学习的心脏病预测 在当今数字化时代&#xff0c;机器学习的应用已经渗透到了医疗保健领域的各个层面。其中&…

阿里云/腾讯云幻兽帕鲁服务器为什么更新/重启之后,服务器存档没了?

有的朋友说&#xff0c;他的阿里云幻兽帕鲁服务器重启了一下后&#xff0c;服务器存档就没了&#xff1f;这是怎么回事呢&#xff0c;其实可能的原因&#xff0c;一是服务器还有重启完成&#xff0c;也就是游戏服务端还没有启动&#xff0c;就登进去&#xff0c;可能会显示网络…

Eclipse项目间的引用

我们在开发的时候&#xff0c;有时候需要把一个大的项目打散&#xff0c;尤其是现在微服务的架构很流行&#xff0c;一个大的项目往往被拆成很多小的项目&#xff0c;而有的项目作为公共工程被独立出来&#xff0c;比如有个工程专门提供各种Util工具类&#xff0c;有的工程专门…

使用 Docker 安装 Elasticsearch 8.4.3

使用 Docker 安装 Elasticsearch 8.4.3 一. 拉取 Elasticsearch Docker 镜像二. 使用Docker启动单节点集群三. 修改密码 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 从 Elastic…

基于Python的热点分析预警系统

项目&#xff1a;基于Python的热点分析预警系统 摘 要 基于网络爬虫的数据可视化服务系统是一种能自动从网络上收集信息的工具&#xff0c;可根据用户的需求定向采集特定数据信息的工具&#xff0c;本项目通过研究爬取微博网来实现微博热点分析数据信息可视化系统功能。对于采…

美国纽约时代广场纳斯达克大屏投放-大舍传媒

美国纽约时代广场纳斯达克大屏投放-大舍传媒 引言 对于大舍传媒来说&#xff0c;能够在美国纽约时代广场纳斯达克大屏投放广告是一个里程碑式的时刻。这不仅仅代表着大舍传媒在全球范围内的知名度与实力&#xff0c;也标志着该公司在国际市场上取得了巨大的进展。纽约时代广场…

sqllabs第46关 order by 注入

简介&#xff1a;&#xff08;order by注入-错误回显-POST注入&#xff09; 请求方法&#xff1a;POST 方法&#xff1a;order by注入错误回显数字型注入 先了解下 order by参数注入&#xff1a; order by 注入是指其后面的参数是可控的&#xff0c; order by 不同于我们在 whe…

威来国际教育:留学服务的全新标杆,打造无忧留学体验

在当今全球化日益加深的背景下&#xff0c;留学已成为众多年轻人拓宽视野、提升个人能力的重要手段。随着留学市场的不断扩大和留学目的地的多样化&#xff0c;家庭和学生在选择留学服务时更加注重专业性和全面性。 在这一领域&#xff0c;威来国际教育凭借其深厚的背景和专业的…

一、vue3+ts项目框架搭建——规范

新建项目及规范配置 1.1项目初始化 1.1.1环境准备1.1.2初始化项目 1.2项目配置 一、eslint配置 1.1vue3环境代码校验插件1.2.eslintrc.cjs配置文件 1.3运行脚本 二、配置prettier:格式化工具 2.1安装依赖包2.2.prettierrc.json添加规则2.3.prettierignore忽略文件 三、配置st…

Vue3-组合式Api(重点)

阅读文章你可以收获的知识 1.知道setup语法糖的使用和如何实现的 2.知道在vue3中如何定义响应式数据 3.知道在vue3中如何定义一个计算属性&#xff08;computed&#xff09; 4.知道如何在vue3中使用watch来监听数据 5.知道在vue3如何实现父子通信 6.知道vue3如何使用ref函…

苍穹外卖学习-----2024/02/21

1.新增员工 /*** 处理SQL异常* param sqlIntegrityConstraintViolationException* return*/ExceptionHandlerpublic Result exceptionHandler(SQLIntegrityConstraintViolationException sqlIntegrityConstraintViolationException){//String message sqlIntegrityConstraintV…

JS实现根据数组对象的某一属性排序

JS实现根据数组对象的某一属性排序 一、冒泡排序&#xff08;先了解冒泡排序机制&#xff09;二、根据数组对象的某一属性排序&#xff08;引用sort方法排序&#xff09; 一、冒泡排序&#xff08;先了解冒泡排序机制&#xff09; 以从小到大排序为例&#xff0c;冒泡排序的原…

2.20日学习打卡----初学Vue3

2.20日学习打卡 目录: 2.20日学习打卡Vue是什么&#xff1f;安装vue模板语法条件渲染列表渲染事件处理表单输入绑定组件基础Props组件交互自定义事件组件交互组件生命周期Vue引入第三方Axios网络请求Axios网络请求封装网络请求跨域解决方案路由配置路由传递参数嵌套路由配置Vue…

面向对象编程入门:掌握C++类的基础(1/3)

面向对象编程&#xff08;OOP&#xff09;是一种编程范式&#xff0c;它使用“对象”来设计软件。在C中&#xff0c;类是创建对象的蓝图。本文将介绍类的基本概念&#xff0c;帮助初学者理解如何在C中使用类来实现面向对象编程。 ​​​​​​​ 1. 类的引入 在深入探讨类的…

【专利】专利缴费清单与汇款金额不一致的处理方法

缴纳专利年费时&#xff0c;很容易算错滞纳金。比如有个专利年费滞纳金应交690&#xff0c;结果我算成了660&#xff0c;报给财务转账660。第二天补录缴费信息时&#xff0c;汇款金额660&#xff0c;然后缴费清单填写总是690无法修改&#xff0c;导致无法进行下一步&#xff01…

Python 写网络监控

大家好&#xff01;我是爱摸鱼的小鸿&#xff0c;关注我&#xff0c;收看每期的编程干货。 网络监控是保障网络可靠性的一项重要任务。通过实时监控网络性能&#xff0c;我们可以及时发现异常&#xff0c;迅速采取措施&#xff0c;保障网络畅通无阻。本文将以 Python为工具&…

云性能监控有着至关重要的作用

随着云计算的蓬勃发展&#xff0c;云性能监控成为保障云应用顺畅运行的不可或缺的一环。本文将介绍云性能监控的主要作用&#xff0c;以便更好地理解为什么它对于云环境中的应用程序至关重要。 1. 实时性能反馈 云性能监控提供了对应用程序性能的实时反馈。通过监测关键性能指标…