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

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>

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 阿奇科技 简单java-swing计算器源码(可用于课设等)
  • 小程序 UI 风格,赏心悦目
  • Linux安装Docker | 使用国内镜像
  • upload-labs-第五关
  • [AI Google] 使用 Gemini 取得更多成就:试用 1.5 Pro 和更多智能功能
  • 1、深度学习-安装
  • DDMA信号处理以及数据处理的流程---DDMA原理介绍
  • MySQL之查询性能优化(八)
  • Android13 Settings 左上角箭头图标点击无效
  • 数 据 类 型
  • 10、架构-从类库到服务之网关路由
  • 基于Java+SpringBoot制作一个软考助手答题小程序
  • 亚马逊 AWS 视频转码功能、AWS Elemental MediaConvert 中创建和管理转码作业
  • 如何获取MySQL中表的大小?(官方校正版)
  • 【深度学习】—— 神经网络介绍
  • hexo+github搭建个人博客
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • android 一些 utils
  • Angular4 模板式表单用法以及验证
  • CEF与代理
  • eclipse的离线汉化
  • Joomla 2.x, 3.x useful code cheatsheet
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • Magento 1.x 中文订单打印乱码
  • pdf文件如何在线转换为jpg图片
  • php面试题 汇集2
  • Sass Day-01
  • Spark RDD学习: aggregate函数
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • vue-cli3搭建项目
  • vue总结
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 闭包,sync使用细节
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 高度不固定时垂直居中
  • 力扣(LeetCode)21
  • 使用 Docker 部署 Spring Boot项目
  • 推荐一个React的管理后台框架
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • Java数据解析之JSON
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​油烟净化器电源安全,保障健康餐饮生活
  • ​字​节​一​面​
  • #DBA杂记1
  • #Z0458. 树的中心2
  • #大学#套接字
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (arch)linux 转换文件编码格式
  • (Forward) Music Player: From UI Proposal to Code