需求
因为在做的项目中,有多个网站登录同一个用户,故想在某一个页面登录或者退出的时候,对其他页面进行相同的操作
跨域,跨页面,跨项目,跨标签页,https
因为一开始不像麻烦后端,所以先尝试了很多前端解决的方法
- localStorage:可以跨页面,不可跨域
- eventbus:不可跨页
- Broadcast Channel API:不可跨项目,不可跨页面
- postMessage:https的情况下 不能跨域,本地可以跨
总之是用前端的方法没有解决这个问题,最后选择了用websocket,完美解决
实现:
目前实现的需求是vue2组件获取浏览器的唯一指纹来确定给后台的信息标识,
比如我打开了10个有这个组件的页面 那么就是会有10发10个消息,
但是他们的id是相同的,如果这1个页面中有一个退出页面 那么其他9个也会跟着退出,这样做目前有个问题是如果开的太多了不确定压力测试能不能过
java部分
- java代码在github上:
- https://github.com/Shi-haoD/webSocketDemo/tree/main
注意事项:
java
WebSocketServer文件中的onMessage方法:收到的报文形式需要时json格式的{key:'value'}
其他的代码里面都有注释
前端部分
javascript
<template>
<div></div>
</template>
<script>
export default {
name: '',
components: {},
mixins: [],
props: {},
data() {
return {
socket: null,
murmurs:''
};
},
computed: {},
watch: {},
mounted() {
this.getmur();
//调用 发送消息
this.sendMessage('退出登录', '');
},
methods: {
//获取浏览器指纹
async getmur() {
this.murmurs = await new Promise((resolve) => {
Fingerprint2.get(function (components) {
const values = components.map(function (component, index) {
if (index === 0) {
// 把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
return component.value.replace(
/\bNetType\/\w+\b/,
''
);
}
return component.value;
});
// 生成最终id murmur
const murmur = Fingerprint2.x64hash128(values.join(''), 31);
resolve(murmur);
});
});
console.log('指纹指纹指纹');
this.getSocket();
},
// 初始化WebSocket连接
getSocket() {
console.log('尝试连接 WebSocket');
if (typeof WebSocket === 'undefined') {
console.log('您的浏览器不支持WebSocket');
return;
}
console.log('您的浏览器支持WebSocket');
let socketUrl =
'http://localhost/socket/imserver/' +
this.murmurs;
socketUrl = socketUrl.replace('https', 'ws').replace('http', 'ws');
console.log('WebSocket URL:', socketUrl);
this.socket = new WebSocket(socketUrl);
// 打开事件
this.socket.onopen = () => {
console.log('WebSocket连接已打开');
this.startHeartbeat(); // 开启心跳机制
};
// 收到消息事件
this.socket.onmessage = (msg) => {
console.log('收到消息:', msg.data);
if (
msg.data === '连接成功' ||
msg.data === 'heartbeat' ||
typeof msg.data === 'string'
) {
console.log(msg.data);
return;
}
let jsonMsg = {};
try {
jsonMsg = JSON.parse(msg.data);
} catch (e) {
console.error('解析消息失败:', e);
return;
}
};
// 关闭事件
this.socket.onclose = () => {
console.log('WebSocket连接已关闭');
this.stopHeartbeat(); // 停止心跳机制
};
// 错误事件
this.socket.onerror = (error) => {
console.log('WebSocket发生了错误:', error);
};
},
// 向服务器发送消息
sendMessage(content, userName) {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
const message = JSON.stringify({
toUserId: 'toUserId',
contentText: 'contentText',
userName: 'userName',
});
console.log('发送消息:', message);
this.socket.send(message);
} else {
console.log('WebSocket连接未打开,无法发送消息');
}
},
// 开启心跳机制
startHeartbeat() {
if (this.socket) {
console.log('启动心跳机制');
this.heartbeatInterval = setInterval(() => {
if (this.socket.readyState === WebSocket.OPEN) {
let hertmessage = JSON.stringify({
type: 'heartbeat',
});
this.socket.send(hertmessage);
}
}, 30000); // 每30秒发送一次心跳包
}
},
// 停止心跳机制
stopHeartbeat() {
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval);
this.heartbeatInterval = null;
console.log('停止心跳机制');
}
},
},
};
</script>
<style lang="" scoped></style>