最近公司开发的项目管理软件需要加入即时通讯功能,后端基于springboot+netty+ws,本人被迫从java开发工程师转型成全栈,如果代码有什么问题欢迎指出

后端功能开发参考了github的开源项目 上链接https://github.com/lmxdawn/him-netty

前端采用uniapp提供的wsAPI,微信小程序或web端实现思路也是一样的
实现ws登录,心跳,断线重连的功能

vuex的功能不用多说 不懂的可以先学习一下

在项目根目录下创建文件:  /common/websocketStore.js

注释很全就不多作说明了

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)


export default new Vuex.Store({
	state: {
		socketTask: null, // ws链接
		webSocketPingTimer: null, // 心跳定时器
		webSocketPingTime: 10000, // 心跳的间隔,当前为 10秒,
		webSocketReconnectCount: 0, // 重连次数
		webSocketIsReconnect: true, // 是否重连
		webSocketIsOpen: true,
		uid: null, //ws登录userId
		sid: null, //ws登录token
		msg: null //接收到的信息
	},
	getters: {
		// 获取接收的信息
		socketMsgs: state => {
			return state.msg
		}
	},
	mutations: {
		//发送http请求登录后设置用户id 用于ws登录
		setUid(state, uid) {
			state.uid = uid
		},
		//发送http请求登录后设置用户token 用于ws登录
		setSid(state, sid) {
			state.sid = sid
		},

		//初始化ws 用户登录后调用
		webSocketInit(state) {
			let that = this
			// 创建一个this.socketTask对象【发送、接收、关闭socket都由这个对象操作】
			state.socketTask = uni.connectSocket({
				url: "ws://196.192.168.169:9001/ws",
				success(data) {
					console.log("websocket连接成功");
				},
			});

			// ws连接开启后登录验证
			state.socketTask.onOpen((res) => {
				console.log("WebSocket连接正常打开中...!");
				that.commit('webSocketLogin')
				//开始心跳
				that.commit('webSocketPing')
				// 注:只有连接正常打开中 ,才能正常收到消息
				state.socketTask.onMessage((res) => {
					console.log("收到服务器内容:" + res.data);
					state.msg = JSON.parse(res.data)
				});

			});

			// 链接开启后登录验证
			state.socketTask.onError((errMsg) => {
				console.log(errMsg)
				console.log("ws连接异常")
				that.commit('webSocketClose')
			});

			// 链接开启后登录验证
			state.socketTask.onClose((errMsg) => {
				console.log(errMsg)
				console.log("ws连接关闭")
				that.commit('webSocketClose')
			});

		},

		webSocketLogin() {
			let that = this
			
			console.log("ws登录");
			const payload = {
				uid: that.state.uid,
				sid: that.state.sid,
				type: 1
			};
			that.commit('webSocketSend', payload);
			that.state.webSocketIsOpen = true
		},

		// 断开连接时
		webSocketClose(state) {
			let that = this
			// 修改状态为未连接
			state.webSocketIsOpen = false;
			state.webSocket = null;
			// 判断是否重连
			if (
				state.webSocketIsReconnect &&
				state.webSocketReconnectCount === 0
			) {
				// 第一次直接尝试重连
				that.commit('webSocketReconnect');
			}
		},

		// 定时心跳
		webSocketPing() {
			let that = this
			that.state.webSocketPingTimer = setTimeout(() => {
				if (!that.state.webSocketIsOpen) {
					return false;
				}
				console.log("心跳");
				const payload = {
					type: 0
				};
				that.commit('webSocketSend', payload);
				clearTimeout(that.state.webSocketPingTimer);
				// 重新执行
				that.commit('webSocketPing');
			}, that.state.webSocketPingTime);
		},

		// WebSocket 重连
		webSocketReconnect(state) {
			let that = this
			if (state.webSocketIsOpen) {
				return false;
			}
			console.log("第"+state.webSocketReconnectCount+"次重连")
			state.webSocketReconnectCount += 1;
			// 判断是否到了最大重连次数 
			if (state.webSocketReconnectCount >= 10) {
				this.webSocketWarningText = "重连次数超限";
			    return false;
			}
			// 初始化
			console.log("开始重连")
			that.commit('webSocketInit');

			// 每过 5 秒尝试一次,检查是否连接成功,直到超过最大重连次数
			let timer = setTimeout(() => {
				that.commit('webSocketReconnect');
				clearTimeout(timer);
			}, 5000);
		},

		// 发送ws消息
		webSocketSend(state, payload) {
			let that = this
			that.state.socketTask.send({
				data: JSON.stringify(payload),
				fail: function(res){
					console.log("发送失败")
					that.state.sendMsgStatus = true
				},
				success: function(res){
					console.log("发送成功")
					that.state.sendMsgStatus = false
				}
			})
		}
	},


	actions: {
		webSocketInit({
			commit
		}, url) {
			commit('webSocketInit', url)
		},
		webSocketSend({
			commit
		}, p) {
			commit('webSocketSend', p)
		}
	}
})

在项目根路径main.js下全局引入js

import websocket from '@/common/websocketStore.js'

Vue.prototype.$websocket = websocket;

成功登录的回调方法中设置 uid,sid

let that = this
that.$websocket.commit('setUid',res.data.id)
that.$websocket.commit('setSid',res.data.apiKey)
that.$websocket.dispatch('webSocketInit');//初始化ws

在需要接收消息的页面接受并处理消息

computed: {
    //监听接收到的消息
	socketMsgs() {
		return this.$websocket.getters.socketMsgs
    }
},
watch: {
	'socketMsgs': {
        //处理接收到的消息
		handler: function() {
		    let that = this
			console.log("接收到msg")
			let sMsg = that.socketMsgs
			console.log(sMsg)
          }
	}
},

app.vue添加代码 实现微信后台心跳失败 重连

//应用生命周期 onShow	当 uni-app 启动,或从后台进入前台显示
onShow: function() {
	let that = this
	if(that.$websocket.getters.sendMsgStatus){
		that.$websocket.dispatch('webSocketInit');
	}
}

 

Logo

前往低代码交流专区

更多推荐