微服务使用SockJs+Stomp实现Websocket 前后端实例 | Vuex形式断开重连、跨域等等问题踩坑(二)

大家好,我是程序员大猩猩。

上次我们实践了,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.js

const files = require.context('.', false, /\.js$/)
const modules = {}

files.keys().forEach(key => {
    if (key === './index.js') return
    modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})

export default modules

// websocket.js

import {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 = url
            if (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 = this
        console.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

​​​​​​​

相关推荐
Starwow23 分钟前
微服务之gRPC
后端·微服务·golang
pursue.dreams41 分钟前
Spring Boot整合T-IO实现即时通讯
spring boot·websocket·t-io
mokkaio2 小时前
如何设计代码逻辑
架构
omnibots2 小时前
ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(输入类外设之触摸屏 Touch)
嵌入式硬件·架构·iot
森叶2 小时前
Java NIO & Java 虚拟线程(微线程)与 Go 协程的运行原理不同 为何Go 能在低配机器上承接10万 Websocket 协议连接
java·websocket·nio
00后程序员张3 小时前
iPhone相册导出到电脑的完整指南
websocket·网络协议·tcp/ip·http·网络安全·https·udp
行墨4 小时前
Replugin 的hook点以及hook流程
android·架构
Yharim4 小时前
微服务项目相同nacos地址导致的问题
后端·微服务
桂月二二4 小时前
Vue3服务端渲染(SSR)深度调优:架构裂变与性能突围
架构
SimonKing4 小时前
短信被截断?5分钟用Java打造企业级短链服务
java·后端·架构