fix 修复 push 模块 sse/ws 浏览器多标签页互挤掉线问题

This commit is contained in:
疯狂的狮子Li
2026-06-25 17:23:44 +08:00
parent e8b033c4ef
commit eab4228548
3 changed files with 35 additions and 0 deletions
@@ -31,4 +31,9 @@ public interface MessageConstants {
* 心跳响应标识
*/
String PONG = "pong";
/**
* 同一 token 的新连接替换旧连接时发送给旧连接的控制消息。
*/
String KICKED = "kicked";
}
@@ -65,6 +65,7 @@ public class SseEmitterSessionManager implements PushSessionManager {
// 关闭已存在的SseEmitter,防止超过最大连接数
SseEmitter oldEmitter = emitters.remove(token);
if (oldEmitter != null) {
sendKickedMessage(oldEmitter);
oldEmitter.complete();
}
@@ -103,6 +104,21 @@ public class SseEmitterSessionManager implements PushSessionManager {
return emitter;
}
/**
* 通知旧连接已被同 token 新连接替换。
*
* @param emitter 旧 SSE 连接
*/
private void sendKickedMessage(SseEmitter emitter) {
try {
emitter.send(SseEmitter.event()
.name("message")
.data(MessageConstants.KICKED));
} catch (Exception ignore) {
// 旧连接可能已断开,忽略通知失败
}
}
/**
* 断开指定用户的 SSE 连接
*
@@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.ThreadUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.push.constant.MessageConstants;
import org.dromara.common.push.dto.PushDTO;
import org.dromara.common.push.properties.MessageProperties;
import org.dromara.common.redis.utils.RedisUtils;
@@ -61,6 +62,7 @@ public class WebSocketSessionManager implements PushSessionManager {
Map<String, WebSocketSession> sessions = USER_TOKEN_SESSIONS.computeIfAbsent(userId, key -> new ConcurrentHashMap<>());
// 移除并关闭旧的同token会话,避免重复连接
WebSocketSession oldSession = sessions.remove(token);
sendKickedMessage(oldSession);
closeSession(oldSession, CloseStatus.NORMAL);
// 存储新会话
sessions.put(token, session);
@@ -129,6 +131,18 @@ public class WebSocketSessionManager implements PushSessionManager {
toRemoveUsers.forEach(USER_TOKEN_SESSIONS::remove);
}
/**
* 通知旧连接已被同 token 新连接替换。
*
* @param session 旧 WebSocket 会话
*/
private void sendKickedMessage(WebSocketSession session) {
if (session == null || !session.isOpen()) {
return;
}
sendMessage(session, MessageConstants.KICKED);
}
/**
* 订阅消息通道
* 注册消息消费者,监听Redis消息推送