大家好,我是程序员大猩猩。
上次我们实践了,Java后端如何完成SockJS+Stomp的配置实现。
微服务使用SockJs+Stomp实现Websocket 前后端实例 | Vuex形式断开重连、跨域等等问题踩坑(一) |
那么今天我们做一下web vue端的是如何来实现的。
这里我罗列一下,我实现所使用的vue版本。
"sockjs-client": "^1.5.0",
"stompjs": "^2.3.3",
"vue": "^3.0.0",
"vuex": "^4.1.0"
// 本地Node版本号
node v14.21.3
这里,我从创建好工程后,导入工程开始说起,说说我碰到的问题及我的解决方法,一遍大家更好的理解。
首先,我是采用vue create *** 来创建一个项目,中间选择使用vuex组件。待项目创建后,我这里使用WebStorm开发工具,将项目导入后,工具会自动让我们npm install。
在项目的根目录
npm install sockjs-client
npm install stompjs
或者
package.json->dependencies->下添加
"sockjs-client": "^1.5.0",
"stompjs": "^2.3.3",
因为我们是需要在vuex中实现SockJs的,所以在src内创建store目录,并且完成一下代码store/index.js
import modules from './modules'import { createStore } from 'vuex'
export default new createStore({modules,strict: false
})
在store目录下创建modules文件目录,目录内新增index.js和websocket.js
// index.jsconst files = require.context('.', false, /\.js$/)
const modules = {}files.keys().forEach(key => {if (key === './index.js') returnmodules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})export default modules// websocket.jsimport {createStore} from 'vuex'
import SockJS from 'sockjs-client'
import Stomp from 'stompjs'
import config from '../../config/index'
// 后端ws连接 http开头形式
const url = config.scokJsUrl
接下来我们分析一下,websocket在前端需要什么操作呢?
1. 初始化
WEBSOCKET_INIT({commit,state}, header) {commit('WEBSOCKET_INIT', header)
},
2. 发送消息
WEBSOCKET_SEND({commit,state}, p) {commit('WEBSOCKET_SEND', p)
},
3. 订阅
WEBSOCKET_UNSUBSRCIBE({commit,state}, p) {commit('WEBSOCKET_UNSUBSRCIBE', p)
},
4. 断开
WEBSOCKET_DISCONNECT({commit,state}) {commit('WEBSOCKET_DISCONNECT')
}
我们在store注册actions,actions注册以上方法。然后在mutations内实现以上方法。
mutations: {WEBSOCKET_INIT(state, header) {if (state.stompClient == null || !state.stompClient.connected) {state.url = urlif (state.stompClient != null && state.websocket.readyState === SockJS.OPEN) {state.stompClient.disconnect(() => {this.commit('WEBSOCKET_CONNECT', header)})} else if (state.stompClient != null && state.websocket.readyState === SockJS.CONNECTING) {console.log('连接正在建立')return} else {this.commit('WEBSOCKET_CONNECT', header)}// 断线重连实现块// 断线重连实现块// 断线重连实现块// 断线重连实现块} else {console.log('连接已建立成功,不再执行')}},WEBSOCKET_CONNECT(state, header) {const _this = thisconsole.log('URL链接 ' + state.url)const websock = new SockJS(state.url)console.log('URL链接 ' + websock)state.websocket = websock// 获取STOMP子协议的客户端对象const stompClient = Stomp.over(websock)stompClient.connect(header,() => {console.log('链接成功!')state.listenerList.forEach(item => {state.stompClient.subscribe(item.topic, item.callback, header)})},(err) => {console.log('链接失败!', err)// 第一次连接失败和连接后断开连接都会调用这个函数 此处调用重连setTimeout(() => {_this.commit('WEBSOCKET_INIT', header)}, 1000)})state.stompClient = stompClient},WEBSOCKET_SEND(state, p) {state.stompClient.send(p.topic, {userId: p.userId}, p.data)},WEBSOCKET_UNSUBSRCIBE(state, p) {state.stompClient.unsubscribe(p)for (let i = 0; i < state.listenerList.length; i++) {if (state.listenerList[i].topic === p) {state.listenerList.splice(i, 1)console.log('解除订阅:' + p + ' size:' + state.listenerList.length)break}}},WEBSOCKET_DISCONNECT(state) {if (state.stompClient != null) {console.log('关闭连接')state.stompClient.disconnect()}}
},
sockJs主要连接代码为WEBSOCKET_CONNECT内:
const websock = new SockJS(state.url)
console.log('URL链接 ' + websock)
state.websocket = websock
// 获取STOMP子协议的客户端对象
const stompClient = Stomp.over(websock)
当websocket.js实现完成后,我们也基本完成的vue端的实现,接下来在现实端页面,调用vuex即可。参考我的methods
methods: {disconnect() {clearInterval(this.connectionTimer);clearInterval(this.timer);this.$websocket.dispatch("WEBSOCKET_DISCONNECT");},stompConnection() {const loginUserId = "my you Dad";const headers = {token: "SSSRIRTOKEN326458",userId: loginUserId};this.$websocket.dispatch("WEBSOCKET_INIT", headers);const _this = this;const stompClient = this.$websocket.getters.stompClient();this.connectionTimer = setInterval(() => {if (stompClient != null && stompClient.connected) {clearInterval(this.connectionTimer);_this.subscriptions = [];_this.subscriptions.push(stompClient.subscribe("/user/" + loginUserId + "/queue/ping", msg => {console.log("我要的ping信息" + msg.body);}));// 定时推送订阅信息this.timer = setInterval(function () {const header = {userId: loginUserId};stompClient.send("/ping", header, "ping");}, 10000);} else {console.log("等待连接成功");}}, 500);}
}
前后端一起启动项目,查看结果。
StompJS的一些设置:
// 关闭控制台打印
// stompClient.debug = null
// stompClient.heartbeat.outgoing = 20000
// // 客户端不从服务端接收心跳包
// stompClient.heartbeat.incoming = 0