vue实现stompjs+websocket和后端通信(二)

        vue项目的搭建在这里就不说了,网上有很多教程。大家自行百度。前端使用stomp+websocket有很多的实现版本。这里只讲@stomp/stompjs方式实现。

导入

使用@stomp/stompjs需要执行安装命令:

import Stomp from '@stomp/stompjs';

 然后在组件中引入即可,这里需要注意的是,可能由于版本不一致,会导致引入的方式不一致。但是主要是以下两种方式中的一种

import { Client, Stomp} from '@stomp/stompjs';

或者
import Stomp from '@stomp/stompjs';

 连接服务器

        连接服务器需要用到connect()方法。该方法有一个基本的成功时的回调函数

var connect_success_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);
};
// 创建Stomp客户端实例let stompClient = Stomp.client('ws://localhost:7000/websocket-demo/stmpwebsocket');// 连接WebSocketstompClient.connect(frame => {console.log('Connected: ' + frame);//这里表示已经连接成功}, error => {console.error('STOMP error:', error);});

        connect()方法可以传入两个参数,用来做用户认证:用户的登录和密码凭证。在大多数情况下,connect()方法可接受不同数量的参数来提供简单的API:

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

  loginpasscode是strings,connectCallbackerrorCallback则是functions。(有些brokers(代理)还需要传递一个host(String类型)参数。)

        有时候我们的连接没有专门的用户名和密码,都是在原有的已经认证的基础上进行连接,例如token,所以我们需要将token传给后端:这样我们需要一个http类似的请求头实现方式。stomp也支持hear的参数

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

headermap形式,connectCallbackerrorCallback为functions。

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

var headers = {login: 'username',passcode: 'mypasscode',token: 'my-client-id'
};
stompClient.connect(headers, connectCallback);

断开连接

        断开连接使用的时disconnect()方法,该方法接受一个回调函数

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

心跳保活

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

        heart-beating也就是频率,incoming是接收频率,outgoing是发送频率。通过改变incoming和outgoing可以更改客户端的heart-beating(默认为10000ms)。heart-beating是利用window.setInterval()去规律地发送heart-beats或者检查服务端的heart-beats。

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

 消息发送

        消息发送使用send()方法。这个方法必须有一个参数,用来描述对应的STOMP的目的地。另外可以有两个可选的参数:headersobject类型包含额外的信息头部;body,一个String类型的参数。

stompClient.send(describetion, headers,messageBody)

消息订阅和接收

         stomp的数据订阅和接收是同时的,订阅方法需要传入一个数据处理回调函数,函数有且只有一个参数,参数中包含了服务器发送的数据。且该方法会返回一个Promise对象,用于取消数据订阅。

//获取订阅结果用于取消订阅let pushSubscriptionPromise = stompClient.subscribe('subscribePath', message => {// 处理接收到的消息console.log('收到消息', message.body);});

取消订阅

        数据的取消订阅使用订阅方法返回的对象调用unSubscribe()即可

pushUserSubscriptionPromise.unsubscribe()

 消息确认ack

        在收到服务端的数据之后,我们可能需要给后端一个ack'消息,用于告诉后端我们已经收到了消息,这个机制在传输一些很重要的信息是有必要的。

//获取订阅结果用于取消订阅let pushSubscriptionPromise = stompClient.subscribe('subscribePath', message => {// 处理接收到的消息console.log('收到消息', message.body);/ 发送ACK确认消息stompClient.ack(message);});

        stompClient.ack(message)方法用于发送一个ACK确认,表示我们已经收到并处理了ID为message.headers['message-id']的消息。如果你需要显式指定消息ID,可以这样做:

stompClient.ack(message.headers['message-id']);

以上就是使用@stomp/stompjs。

以下是一个完整的组件代码。可直接复制到一个已经搭建好的vue项目上测试。请忽略极其难看的ui页面。

<template><div class="f_c float_l"><div class="m_10 float_l"><el-input class='input_common' v-model="websocketPath" placeholder="后端websocket地址:http://ip:port/context/websocket-point" ></el-input><el-input class='input_common' v-model="userId" placeholder="请输入用户名" ></el-input><el-button v-if="!connected" @click=" connectWebsocket" >连接</el-button><el-button v-else @click="disConnectWebsocket" >断开</el-button></div><el-divider /><div class="f_c" v-if="connected"><div><el-input class='input_common' v-model="messageUrl" placeholder="请输入消息地址:/sendMessage"></el-input><el-button @click="sendMessage" v-if="connected">发送</el-button></div><el-input class='input_common mt_10' v-model="message" type="textarea" :rows="2" placeholder="请输入需要发送的消息"></el-input></div><el-divider /><div class="f_c m_10 float_l" v-if="connected"><div class="float_l"><el-input class='input_common' v-model="subscribePath" placeholder="请输入监听地址:/subscribe/id"></el-input><el-button @click="subscribeTopic" v-if="!subscribed">广播订阅</el-button><el-button @click="unSubscribeTopic" v-else>取消订阅</el-button></div><div class="m_10 f_c"><span class="float_l">收到消息</span><span style="border: aqua; width: 500px; height: 100px">{{receiveMessage}}</span></div></div><div class="f_c m_10 float_l" v-if="connected"><div class="float_l"><el-input class='input_common' v-model="userSubscribePath" placeholder="请输入监听地址:/subscribe/id"></el-input><el-button @click="subscribeUserTopic" v-if="!userSubscribed">用户订阅</el-button><el-button @click="unUserSubscribeTopic" v-else>取消订阅</el-button></div><div class="m_10 f_c"><span class="float_l">收到消息</span><span style="border: aqua; width: 500px; height: 100px">{{receiveUserMessage}}</span></div></div></div>
</template><script>
import { Client, Stomp} from '@stomp/stompjs';export default {name: "index",data(){return {websocketPath:'localhost:7000/websocket-demo/stmpwebsocket',userId:'123456789',subscribePath:'/topic/targetSubscribe',receiveMessage:'',userSubscribePath:'/user/queue/targetUser',receiveUserMessage:'',messageUrl:'/message/stomp/springUserMessage/987654321',message:'',connected: false,subscribed: false,userSubscribed:false,stompClient:null,pushSubscriptionPromise: null,pushUserSubscriptionPromise: null}},methods:{connectWebsocket(){if(!this.websocketPath){this.$message.error("请先填写websocket地址信息")return}if(!this.userId){this.$message.error("请先填写用户信息")return}// 创建Stomp客户端实例this.stompClient = Stomp.client('ws://' + this.websocketPath);//请求头let headers = {'userId': this.userId}// 连接WebSocketthis.stompClient.connect(headers, frame => {console.log('Connected: ' + frame);this.connected = true}, error => {console.error('STOMP error:', error);});},sendMessage(){if(!this.message || !this.messageUrl){this.$message.error("请先填写websocket地址和消息内容信息")return}let msg = { message: this.message };console.log("数据发送:", this.messageUrl, msg)this.stompClient.send(this.messageUrl, {'aaaaaa': 'aaaaaaaaa'}, JSON.stringify(msg));},onceSubscribe(){this.stompClient.subscribe('/message/subscribe/1232131321', function(message) {console.log('onceSubscribe-Message: ' + message.body);})},subscribeTopic(){if(!this.subscribePath){this.$message.error("请先填写订阅地址")return}// 订阅某个路径let number = 1this.subscribed = true//获取订阅结果用于取消订阅this.pushSubscriptionPromise = this.stompClient.subscribe(this.subscribePath, message => {// 处理接收到的消息console.log('收到消息', message);let nowMessage = '第' + number + '次收到订阅的消息:' + JSON.stringify(JSON.parse(message.body)) + '\r\n';this.receiveMessage += nowMessage;number ++;});},subscribeUserTopic(){if(!this.userSubscribePath){this.$message.error("请先填写用户的订阅地址")return}// 订阅某个路径let number = 1this.userSubscribed = true//获取订阅结果用于取消订阅this.pushUserSubscriptionPromise = this.stompClient.subscribe(this.userSubscribePath, message => {// 处理接收到的消息console.log('收到消息', message);let nowMessage = '第' + number + '次收到订阅的消息:' + JSON.stringify(JSON.parse(message.body)) + '\r\n';this.receiveUserMessage += nowMessage;number ++;// 发送ACK确认消息this. stompClient.ack(message);});},unSubscribeTopic(){// 订阅某个路径this.pushSubscriptionPromise.unsubscribe();this.subscribed = false;this.receiveMessage = ''},unUserSubscribeTopic(){// 订阅某个路径this.pushUserSubscriptionPromise.unsubscribe();this.userSubscribed = false;this.receiveUserMessage = ''},disConnectWebsocket(){if (this.stompClient != null) {// 关闭连接this.stompClient.disconnect()this.stompClient = nullthis.connected = falsethis.subscribed = falsethis.userSubscribed = falsethis.receiveMessage = ''this.receiveUserMessage = ''}},beforeDestroy(){if(this.stompClient != null){this.stompClient.disconnect()this.stompClient = nullthis.connected = falsethis.subscribed = falsethis.userSubscribed = falsethis.receiveMessage = ''this.receiveUserMessage = ''}}}
}
</script><style scoped></style>

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

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

相关文章

探索国内大模型AIGC产品

​ 人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗…

2. keepalived结合LVS配合使用

keepalived结合LVS配合使用 1、后端nfs存储提供项目文件2、后端nfs上集中安装MySQL&#xff0c;共用数据库3、业务服务器通过LNMP正常部署wordpress博客&#xff0c;客户端通过DNS解析可正常访问4、所有业务服务器上修改arp参数、配置VIP5、配置keepalived实现LVS高可用5.1 kee…

web前端电影简介标签:深度解析与创意应用

web前端电影简介标签&#xff1a;深度解析与创意应用 在web前端开发中&#xff0c;电影简介标签的设计与实现是一项既具挑战性又充满创意的任务。这些标签不仅需要准确传达电影的核心信息&#xff0c;还要通过精美的设计和交互效果吸引用户的眼球。本文将从四个方面、五个方面…

Python私教张大鹏 Vue3整合AntDesignVue之Dropdown 下拉菜单

基本用法 核心代码&#xff1a; <template><a-dropdown><a class"ant-dropdown-link" click.prevent>Hover me<DownOutlined /></a><template #overlay><a-menu><a-menu-item><a href"javascript:;"…

软件心学格物致知篇(7)软件开发文档写什么

软件心学格物致知篇(7)软件开发文档写什么 前言 当今约束大家生产力的有哪些因素&#xff1f;是编程语言&#xff1f;开发框架&#xff1f;开发IDE&#xff1f;还是自身迫切需要更高水平的技能&#xff1f; 好像上面的每一项技术都在不断发展&#xff0c;也在不断的为我们生…

Spring Event如何优雅实现系统业务解耦

Spring Event如何优雅实现系统业务解耦 一、介绍 Spring事件&#xff08;Spring Event&#xff09;是Spring框架的一项功能&#xff0c;它允许不同组件之间通过发布-订阅机制进行解耦的通信。在Spring中&#xff0c;事件是表示应用程序中特定事件的对象&#xff0c;例如用户注…

java-HashMap 的底层原理

HashMap 是 Java 中最常用的映射数据结构&#xff0c;它存储键值对&#xff08;key-value pairs&#xff09;&#xff0c;并允许使用任何非空对象作为键或值。HashMap 的底层原理主要依赖于数组和链表&#xff08;或红黑树&#xff09;来实现键值对的存储和检索。 以下是 Hash…

嵌入式必会的几条ARM汇编指令

就这几条混个面熟就行 读内存指令&#xff1a;LDR&#xff0c;即Load之意写内存指令&#xff1a;STR&#xff0c;即Store之意加减指令&#xff1a;ADD、SUB跳转&#xff1a;BL&#xff0c;即Branch And Link入栈指令&#xff1a;PUSH出栈指令&#xff1a;POP 此处是学习韦老师…

在win11系统上安装启动Hyper-V

Hyper-V 是微软公司开发的一种虚拟化技术&#xff0c;它允许一台物理计算机运行多个操作系统和应用程序&#xff0c;从而提供更好的资源利用率和系统灵活性。 win系统的linux子系统开启、android studio的虚拟环境都需要这个东西&#xff0c;而在初始的win11系统上可能没有这个…

Nvidia/算能 +FPGA+AI大算力边缘计算盒子:电力巡检智能机器人

聚焦数字经济与双碳经济赛道&#xff0c;专注于提供集中式新能源场站与分布式综合能源数智化整体解决方案&#xff0c;坚持以场站数字化、综合能源数字化双轮驱动发展。依靠专业化人才队伍与丰富的实证基地研究经验&#xff0c;打造成熟、先进的数智新能源研发平台。 在集中式新…

【面经总结】Java基础 - 面向对象

面向对象 什么是面向对象 https://www.bilibili.com/video/BV1wZ4y1B7A7 以对象为核心。 类是对象创建的模板&#xff0c;对象是类的实例。 面向对象三大特性是什么 封装&#xff1a;类的创建者将类具体实现隐藏&#xff0c;使用者只需要使用外部接口即可继承&#xff1a;类…

常用sql

–page– jpa里面的&#xff0c;需要-1Pageable pageable PageRequest.of(pageNumber - 1, pageSize, Sort.by(“classId”).descending()); RepositoryImpl里面的pageable不需要-1 queryListForMySql(sql, pageable, BeanPropertyRowMapper.newInstance(DingStudentDto.class…

Docker Swarm集群部署管理

Docker Swarm集群管理 文章目录 Docker Swarm集群管理资源列表基础环境一、安装Docker二、部署Docker Swarm集群2.1、创建Docker Swarm集群2.2、添加Worker节点到Swarm集群2.3、查看Swarm集群中Node节点的详细状态信息 三、Docker Swarm管理3.1、案例概述3.2、Docker Swarm中的…

Unity Mirror VR联机开发 房间篇

一、需求 在联机时通常有加入房间这个步骤&#xff0c;在mirror示例中也有相应的案例&#xff0c;但是那个比较复杂&#xff0c;我们做教育科普类不需要如此复杂&#xff0c;傻瓜式操作基本就可以了&#xff0c;所以我简化了步骤&#xff0c;省略了点击准备按钮这一步骤&#…

【Web世界探险家】3. CSS美学(二)文本样式

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…

2024-06-10 问AI: 在大语言模型中,ReAct Agents的理论基础是什么

文心一言 在大语言模型中&#xff0c;ReAct Agents的理论基础主要基于以下几个关键点&#xff1a; 推理与行为的结合&#xff1a;ReAct框架的核心思想是将大型语言模型的推理能力和行为能力相结合。这种结合使得模型能够以交错的方式生成推理步骤和特定于任务的操作&#xff0c…

基于深度学习的中文语音识别模型(支持wav、mp4、m4a等所有格式音频上传)【已开源】

基于深度学习的中文语音识别模型&#xff08;支持wav、mp4、m4a等所有格式音频上传&#xff09; 前言 该开源项目旨在提供一个能够自动检测并识别中文语音的模型&#xff0c;支持wav、mp4、m4a等格式的音频文件上传。无论是从录音设备中获取的wav文件&#xff0c;还是从视频中…

CentOS Python 2.7 离线安装 Requests 库保姆级教程

在内网或无网络连接的环境中&#xff0c;Python 开发者经常需要离线安装第三方库。本文将详细介绍如何在 CentOS 系统上&#xff0c;使用 Python 2.7 版本离线安装 Requests 库。Requests 是一个简单易用的 HTTP 库&#xff0c;用于发送各种 HTTP 请求。 前提条件 CentOS 系统…

C++进阶教程

一、引言 C是一种高效、强大且灵活的编程语言&#xff0c;广泛应用于系统软件开发、游戏开发、科学计算等领域。对于已经掌握C基础知识的开发者来说&#xff0c;进阶学习C将帮助他们更深入地理解这门语言&#xff0c;并提升编程能力。本教程将介绍C中的一些高级特性和技术&…

外部排序快速入门详解:基本原理,败者树,置换-选择排序,最佳归并树

文章目录 外部排序1.最基本的外部排序原理2.外部排序的优化2.1 败者树优化方法2.2 置换-选择排序优化方法2.3 最佳归并树 外部排序 为什么要学习外部排序&#xff1f; 答&#xff1a; 在处理数据的过程中&#xff0c;我们需要把磁盘(外存&#xff09;中存储的数据拿到内存中处理…