Browse Source

ws重连优化

master
xie.bx 2 years ago
parent
commit
5dedc178b1
  1. 24
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java
  2. 33
      im-ui/src/api/wssocket.js
  3. 5
      im-ui/src/components/chat/ChatBox.vue
  4. 63
      im-ui/src/view/Home.vue
  5. 19
      im-uniapp/App.vue
  6. 38
      im-uniapp/common/wssocket.js

24
im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java

@ -1,8 +1,10 @@
package com.bx.implatform.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.imclient.IMClient;
@ -198,6 +200,9 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
UserSession session = SessionContext.getSession();
List<GroupMember> members = groupMemberService.findByUserId(session.getUserId());
List<Long> ids = members.stream().map(GroupMember::getGroupId).collect(Collectors.toList());
if(CollectionUtil.isEmpty(ids)){
return Collections.EMPTY_LIST;
}
// 只能拉取最近1个月的
Date minDate = DateTimeUtils.addMonths(new Date(), -1);
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.lambdaQuery();
@ -242,6 +247,16 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
@Override
public void readedMessage(Long groupId) {
UserSession session = SessionContext.getSession();
// 取出最后的消息id
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.lambdaQuery();
wrapper.eq(GroupMessage::getGroupId, groupId)
.orderByDesc(GroupMessage::getId)
.last("limit 1")
.select(GroupMessage::getId);
GroupMessage message = this.getOne(wrapper);
if(Objects.isNull(message)){
return;
}
// 推送消息给自己的其他终端
GroupMessageVO msgInfo = new GroupMessageVO();
msgInfo.setType(MessageType.READED.code());
@ -254,14 +269,7 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
sendMessage.setData(msgInfo);
sendMessage.setSendResult(false);
imClient.sendGroupMessage(sendMessage);
// 记录已读位置
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.lambdaQuery();
wrapper.eq(GroupMessage::getGroupId, groupId)
.orderByDesc(GroupMessage::getId)
.last("limit 1")
.select(GroupMessage::getId);
GroupMessage message = this.getOne(wrapper);
// 记录已读消息位置
String key = StrUtil.join(":",RedisKey.IM_GROUP_READED_POSITION,groupId,session.getUserId());
redisTemplate.opsForValue().set(key, message.getId());

33
im-ui/src/api/wssocket.js

@ -1,19 +1,11 @@
var websock = null;
let rec; //断线重连后,延迟5秒重新创建WebSocket连接 rec用来存储延迟请求的代码
let isConnect = false; //连接标识 避免重复连接
let wsurl = "";
let accessToken = "";
let messageCallBack = null;
let openCallBack = null;
let closeCallBack = null
let init = (url,token) => {
wsurl = url;
accessToken = token;
};
let connect = () => {
let connect = (wsurl,accessToken) => {
try {
if (isConnect) {
return;
@ -25,8 +17,6 @@ let connect = () => {
if (sendInfo.cmd == 0) {
heartCheck.start()
console.log('WebSocket登录成功')
// 登录成功才算连接完成
openCallBack && openCallBack();
} else if (sendInfo.cmd == 1) {
// 重新开启心跳定时
heartCheck.reset();
@ -59,16 +49,16 @@ let connect = () => {
websock.onerror = function() {
console.log('WebSocket连接发生错误')
isConnect = false; //连接断开修改标识
reConnect();
reconnect(wsurl,accessToken);
}
} catch (e) {
console.log("尝试创建连接失败");
reConnect(); //如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接
reconnect(wsurl,accessToken); //如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接
}
};
//定义重连函数
let reConnect = () => {
let reconnect = (wsurl,accessToken) => {
console.log("尝试重新连接");
if (isConnect){
//如果已经连上就不在重连了
@ -76,12 +66,12 @@ let reConnect = () => {
}
rec && clearTimeout(rec);
rec = setTimeout(function() { // 延迟5秒重连 避免过多次过频繁请求重连
connect();
}, 5000);
connect(wsurl,accessToken);
}, 15000);
};
//设置关闭连接
let close = () => {
websock && websock.close();
let close = (code) => {
websock && websock.close(code);
};
@ -136,20 +126,15 @@ let onMessage = (callback) => {
}
let onOpen = (callback) => {
openCallBack = callback;
}
let onClose = (callback) => {
closeCallBack = callback;
}
// 将方法暴露出去
export {
init,
connect,
reconnect,
close,
sendMessage,
onOpen,
onMessage,
onClose
}

5
im-ui/src/components/chat/ChatBox.vue

@ -512,11 +512,13 @@
//
this.scrollToBottom();
this.sendText = "";
this.showSide = false;
//
this.readedMessage()
// 30
let size = this.chat.messages.length;
this.showMinIdx = size > 30 ? size - 30 : 0;
//
this.$nextTick(() => {
this.$refs.sendBox.focus();
@ -573,7 +575,7 @@
.im-chat-box {
>ul {
padding: 20px;
padding: 0 20px;
li {
list-style-type: none;
@ -612,6 +614,7 @@
}
.send-content-area {
position: relative;
display: flex;
flex-direction: column;
height: 100%;

63
im-ui/src/view/Home.vue

@ -74,7 +74,7 @@
data() {
return {
showSettingDialog: false,
lastPlayAudioTime: new Date()-1000
lastPlayAudioTime: new Date() - 1000
}
},
methods: {
@ -84,16 +84,19 @@
this.loadPrivateMessage(this.$store.state.chatStore.privateMsgMaxId);
this.loadGroupMessage(this.$store.state.chatStore.groupMsgMaxId);
// ws
this.$wsApi.init(process.env.VUE_APP_WS_URL, sessionStorage.getItem("accessToken"));
this.$wsApi.connect();
this.$wsApi.onOpen();
this.$wsApi.connect(process.env.VUE_APP_WS_URL, sessionStorage.getItem("accessToken"));
this.$wsApi.onMessage((cmd, msgInfo) => {
if (cmd == 2) {
// ws
this.$wsApi.close(3000)
// 线
this.$message.error("您已在其他地方登陆,将被强制下线");
setTimeout(() => {
location.href = "/";
}, 1000)
this.$alert("您已在其他地方登陆,将被强制下线", "强制下线通知", {
confirmButtonText: '确定',
callback: action => {
location.href = "/";
}
});
} else if (cmd == 3) {
//
this.handlePrivateMessage(msgInfo);
@ -104,20 +107,18 @@
})
this.$wsApi.onClose((e) => {
console.log(e);
if (e.code == 1006) {
//
this.$message.error("连接已断开,请重新登录");
location.href = "/";
} else {
this.$wsApi.connect();
if (e.code != 3000) {
// 线
this.$message.error("连接断开,正在尝试重新连接...");
this.$wsApi.reconnect(process.env.VUE_APP_WS_URL, sessionStorage.getItem("accessToken"));
}
});
}).catch((e) => {
console.log("初始化失败",e);
console.log("初始化失败", e);
})
},
loadPrivateMessage(minId) {
this.$store.commit("loadingPrivateMsg",true)
this.$store.commit("loadingPrivateMsg", true)
this.$http({
url: "/message/private/loadMessage?minId=" + minId,
method: 'get'
@ -126,20 +127,20 @@
msgInfo.selfSend = msgInfo.sendId == this.$store.state.userStore.userInfo.id;
let friendId = msgInfo.selfSend ? msgInfo.recvId : msgInfo.sendId;
let friend = this.$store.state.friendStore.friends.find((f) => f.id == friendId);
if(friend){
this.insertPrivateMessage(friend,msgInfo);
}
if (friend) {
this.insertPrivateMessage(friend, msgInfo);
}
})
if (msgInfos.length == 100) {
//
this.loadPrivateMessage(msgInfos[99].id);
}else{
this.$store.commit("loadingPrivateMsg",false)
} else {
this.$store.commit("loadingPrivateMsg", false)
}
})
},
loadGroupMessage(minId) {
this.$store.commit("loadingGroupMsg",true)
this.$store.commit("loadingGroupMsg", true)
this.$http({
url: "/message/group/loadMessage?minId=" + minId,
method: 'get'
@ -148,15 +149,15 @@
msgInfo.selfSend = msgInfo.sendId == this.$store.state.userStore.userInfo.id;
let groupId = msgInfo.groupId;
let group = this.$store.state.groupStore.groups.find((g) => g.id == groupId);
if(group){
this.insertGroupMessage(group,msgInfo);
if (group) {
this.insertGroupMessage(group, msgInfo);
}
})
if (msgInfos.length == 100) {
//
this.loadGroupMessage(msgInfos[99].id);
}else{
this.$store.commit("loadingGroupMsg",false)
} else {
this.$store.commit("loadingGroupMsg", false)
}
})
},
@ -212,7 +213,7 @@
//
this.$store.commit("insertMessage", msg);
//
if(!msg.selfSend && msg.status != this.$enums.MESSAGE_STATUS.READED){
if (!msg.selfSend && msg.status != this.$enums.MESSAGE_STATUS.READED) {
this.playAudioTip();
}
},
@ -247,7 +248,7 @@
//
this.$store.commit("insertMessage", msg);
//
if(!msg.selfSend && msg.status != this.$enums.MESSAGE_STATUS.READED){
if (!msg.selfSend && msg.status != this.$enums.MESSAGE_STATUS.READED) {
this.playAudioTip();
}
},
@ -257,14 +258,14 @@
location.href = "/";
},
playAudioTip() {
if(new Date() - this.lastPlayAudioTime > 1000){
if (new Date() - this.lastPlayAudioTime > 1000) {
this.lastPlayAudioTime = new Date();
let audio = new Audio();
let url = require(`@/assets/audio/tip.wav`);
audio.src = url;
audio.play();
}
}
},
showSetting() {
this.showSettingDialog = true;

19
im-uniapp/App.vue

@ -28,10 +28,8 @@
},
initWebSocket() {
let loginInfo = uni.getStorageSync("loginInfo")
let userId = store.state.userStore.userInfo.id;
wsApi.init(process.env.WS_URL, loginInfo.accessToken);
wsApi.connect();
wsApi.onOpen()
wsApi.init();
wsApi.connect(process.env.WS_URL, loginInfo.accessToken);
wsApi.onMessage((cmd, msgInfo) => {
if (cmd == 2) {
// 线
@ -49,20 +47,15 @@
}
});
wsApi.onClose((res) => {
// 10063000APP
if (res.code == 1006) {
uni.showToast({
title: '连接已断开,请重新登录',
icon: 'none',
})
this.exit();
} else if (res.code != 3000) {
// 3000
if (res.code != 3000) {
//
uni.showToast({
title: '连接已断开,尝试重新连接...',
icon: 'none',
})
wsApi.connect();
let loginInfo = uni.getStorageSync("loginInfo")
wsApi.reconnect(process.env.WS_URL, loginInfo.accessToken);
}
})
},

38
im-uniapp/common/wssocket.js

@ -1,20 +1,12 @@
let wsurl = "";
let accessToken = "";
let openCallBack = null;
let messageCallBack = null;
let closeCallBack = null;
let isConnect = false; //连接标识 避免重复连接
let hasInit = false;
let rec = null;
let init = () => {
let init = (url, token) => {
wsurl = url;
accessToken = token;
// 防止重新注册事件
if(hasInit){
return;
}
hasInit = true;
uni.onSocketOpen((res) => {
console.log("WebSocket连接已打开");
isConnect = true;
@ -35,8 +27,6 @@ let init = (url, token) => {
if (sendInfo.cmd == 0) {
heartCheck.start()
console.log('WebSocket登录成功')
// 登录成功才算连接完成
openCallBack && openCallBack();
} else if (sendInfo.cmd == 1) {
// 重新开启心跳定时
heartCheck.reset();
@ -48,7 +38,6 @@ let init = (url, token) => {
})
uni.onSocketClose((res) => {
console.log(res)
console.log('WebSocket连接关闭')
isConnect = false; //断开后修改标识
closeCallBack && closeCallBack(res);
@ -64,7 +53,9 @@ let init = (url, token) => {
})
};
let connect = ()=>{
let connect = (url, token)=>{
wsurl = url;
accessToken = token;
if (isConnect) {
return;
}
@ -83,6 +74,18 @@ let connect = ()=>{
});
}
//定义重连函数
let reconnect = (wsurl,accessToken) => {
console.log("尝试重新连接");
if (isConnect){
//如果已经连上就不在重连了
return;
}
rec && clearTimeout(rec);
rec = setTimeout(function() { // 延迟15秒重连 避免过多次过频繁请求重连
connect(wsurl,accessToken);
}, 15000);
};
//设置关闭连接
let close = () => {
@ -142,9 +145,6 @@ function onMessage(callback) {
messageCallBack = callback;
}
function onOpen(callback) {
openCallBack = callback;
}
function onClose(callback) {
closeCallBack = callback;
@ -155,9 +155,9 @@ function onClose(callback) {
export {
init,
connect,
reconnect,
close,
sendMessage,
onMessage,
onOpen,
onClose
}
Loading…
Cancel
Save