refactor: 优化项目结构
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package com.youlai.boot.support.websocket.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 字典变更事件
|
||||
* <p>
|
||||
* 当字典数据发生变更时,通过 WebSocket 广播此事件通知前端清除缓存。
|
||||
* 前端收到通知后清除对应字典的本地缓存,下次使用时重新从服务端加载。
|
||||
*
|
||||
* @author Ray.Hao
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DictChangeEvent implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 字典编码 */
|
||||
private String dictCode;
|
||||
|
||||
/** 事件时间戳 */
|
||||
private long timestamp;
|
||||
|
||||
/**
|
||||
* 创建字典变更事件(自动设置当前时间戳)
|
||||
*
|
||||
* @param dictCode 字典编码
|
||||
*/
|
||||
public DictChangeEvent(String dictCode) {
|
||||
this.dictCode = dictCode;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.youlai.boot.support.websocket.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 在线用户信息DTO
|
||||
* <p>
|
||||
* 用于返回在线用户的基本信息,包括用户名、会话数量和登录时间。
|
||||
*
|
||||
* @author Ray.Hao
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OnlineUserDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 用户名 */
|
||||
private String username;
|
||||
|
||||
/** 会话数量(多设备登录时大于1) */
|
||||
private int sessionCount;
|
||||
|
||||
/** 最早登录时间 */
|
||||
private long loginTime;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.youlai.boot.support.websocket.job;
|
||||
|
||||
import com.youlai.boot.support.websocket.publisher.WebSocketPublisher;
|
||||
import com.youlai.boot.support.websocket.session.UserSessionRegistry;
|
||||
import com.youlai.boot.support.websocket.topic.WebSocketTopics;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 在线用户数统计定时任务
|
||||
* <p>
|
||||
* 定时统计并广播当前在线用户数量到所有WebSocket客户端。
|
||||
* 用于解决以下问题:
|
||||
* <ul>
|
||||
* <li>客户端页面刷新后可快速同步最新在线人数</li>
|
||||
* <li>减少服务端主动推送频率,降低资源消耗</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Ray.Hao
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class OnlineUserCountJob {
|
||||
|
||||
private final UserSessionRegistry userSessionRegistry;
|
||||
private final WebSocketPublisher webSocketPublisher;
|
||||
|
||||
/**
|
||||
* 定时统计在线用户数并广播
|
||||
* <p>
|
||||
* 每3分钟执行一次,推送当前在线用户数量
|
||||
*/
|
||||
@Scheduled(cron = "0 */3 * * * ?")
|
||||
public void execute() {
|
||||
int onlineCount = userSessionRegistry.getOnlineUserCount();
|
||||
int sessionCount = userSessionRegistry.getTotalSessionCount();
|
||||
|
||||
log.debug("定时统计:在线用户数={}, 总会话数={}", onlineCount, sessionCount);
|
||||
|
||||
// 广播在线用户数量
|
||||
webSocketPublisher.publish(WebSocketTopics.TOPIC_ONLINE_COUNT, onlineCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.youlai.boot.support.websocket.publisher;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tools.jackson.core.JacksonException;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class WebSocketPublisher {
|
||||
|
||||
private SimpMessagingTemplate messagingTemplate;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setMessagingTemplate(SimpMessagingTemplate messagingTemplate) {
|
||||
this.messagingTemplate = messagingTemplate;
|
||||
}
|
||||
|
||||
public void publish(String destination, Object payload) {
|
||||
if (messagingTemplate == null) {
|
||||
log.warn("消息模板尚未初始化,无法发送消息: destination={}", destination);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Object body = serializeIfNeeded(payload);
|
||||
messagingTemplate.convertAndSend(destination, body);
|
||||
} catch (Exception e) {
|
||||
log.error("发送消息失败: destination={}", destination, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void publishToUser(String username, String destination, Object payload) {
|
||||
if (messagingTemplate == null) {
|
||||
log.warn("消息模板尚未初始化,无法发送用户消息: username={}, destination={}", username, destination);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Object body = serializeIfNeeded(payload);
|
||||
messagingTemplate.convertAndSendToUser(username, destination, body);
|
||||
} catch (Exception e) {
|
||||
log.error("发送用户消息失败: username={}, destination={}", username, destination, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Object serializeIfNeeded(Object payload) throws JacksonException {
|
||||
if (payload == null) {
|
||||
return null;
|
||||
}
|
||||
if (payload instanceof String || payload instanceof Number || payload instanceof Boolean) {
|
||||
return payload;
|
||||
}
|
||||
return objectMapper.writeValueAsString(payload);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.youlai.boot.support.websocket.service;
|
||||
|
||||
import com.youlai.boot.support.websocket.dto.OnlineUserDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* WebSocket服务接口
|
||||
* <p>
|
||||
* 提供与WebSocket连接管理相关的功能,包括:
|
||||
* - 用户连接/断开事件处理
|
||||
* - 字典数据变更通知
|
||||
* - 系统消息推送
|
||||
* </p>
|
||||
*
|
||||
* @author Ray.Hao
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public interface WebSocketService {
|
||||
|
||||
/**
|
||||
* 处理用户连接事件
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param sessionId WebSocket会话ID
|
||||
*/
|
||||
void userConnected(String username, String sessionId);
|
||||
|
||||
/**
|
||||
* 处理用户断开连接事件
|
||||
*
|
||||
* @param username 用户名
|
||||
*/
|
||||
void userDisconnected(String username);
|
||||
|
||||
/**
|
||||
* 广播字典数据变更通知
|
||||
*
|
||||
* @param dictCode 字典编码
|
||||
*/
|
||||
void broadcastDictChange(String dictCode);
|
||||
|
||||
/**
|
||||
* 发送系统通知给特定用户
|
||||
*
|
||||
* @param username 目标用户名
|
||||
* @param message 通知消息内容
|
||||
*/
|
||||
void sendNotification(String username, Object message);
|
||||
|
||||
/**
|
||||
* 获取在线用户列表
|
||||
*
|
||||
* @return 在线用户信息列表
|
||||
*/
|
||||
List<OnlineUserDTO> getOnlineUsers();
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
package com.youlai.boot.support.websocket.service.impl;
|
||||
|
||||
import com.youlai.boot.support.websocket.dto.DictChangeEvent;
|
||||
import com.youlai.boot.support.websocket.dto.OnlineUserDTO;
|
||||
import com.youlai.boot.support.websocket.publisher.WebSocketPublisher;
|
||||
import com.youlai.boot.support.websocket.session.UserSessionRegistry;
|
||||
import com.youlai.boot.support.websocket.service.WebSocketService;
|
||||
import com.youlai.boot.support.websocket.topic.WebSocketTopics;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* WebSocket 服务实现类
|
||||
*
|
||||
* 核心功能:
|
||||
* - 用户在线状态管理(支持多设备登录)
|
||||
* - 消息推送(广播、点对点)
|
||||
* - 字典变更通知
|
||||
*
|
||||
* @author Ray.Hao
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class WebSocketServiceImpl implements WebSocketService {
|
||||
|
||||
private final UserSessionRegistry userSessionRegistry;
|
||||
private final WebSocketPublisher webSocketPublisher;
|
||||
|
||||
public WebSocketServiceImpl(UserSessionRegistry userSessionRegistry, WebSocketPublisher webSocketPublisher) {
|
||||
this.userSessionRegistry = userSessionRegistry;
|
||||
this.webSocketPublisher = webSocketPublisher;
|
||||
}
|
||||
|
||||
// ==================== 用户在线状态管理 ====================
|
||||
|
||||
/**
|
||||
* 处理用户连接事件
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param sessionId WebSocket 会话 ID
|
||||
*/
|
||||
@Override
|
||||
public void userConnected(String username, String sessionId) {
|
||||
if (username == null || username.isEmpty()) {
|
||||
log.warn("用户连接失败:用户名为空");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sessionId == null || sessionId.isEmpty()) {
|
||||
log.warn("用户[{}]连接失败:会话 ID 为空", username);
|
||||
return;
|
||||
}
|
||||
|
||||
userSessionRegistry.userConnected(username, sessionId);
|
||||
|
||||
int sessionCount = userSessionRegistry.getUserSessionCount(username);
|
||||
int totalOnlineUsers = userSessionRegistry.getOnlineUserCount();
|
||||
|
||||
log.info("✓ 用户[{}]会话[{}]上线(该用户共 {} 个会话,系统总在线用户数:{})",
|
||||
username, sessionId, sessionCount, totalOnlineUsers);
|
||||
|
||||
// 广播在线用户数变更
|
||||
broadcastOnlineUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理用户断开连接事件
|
||||
*
|
||||
* @param username 用户名
|
||||
*/
|
||||
@Override
|
||||
public void userDisconnected(String username) {
|
||||
if (username == null || username.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
userSessionRegistry.userDisconnected(username);
|
||||
|
||||
int totalOnlineUsers = userSessionRegistry.getOnlineUserCount();
|
||||
log.info("✓ 用户[{}]下线(系统总在线用户数:{})", username, totalOnlineUsers);
|
||||
|
||||
// 广播在线用户数变更
|
||||
broadcastOnlineUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定会话(单个设备下线)
|
||||
*
|
||||
* @param sessionId 会话 ID
|
||||
*/
|
||||
public void removeSession(String sessionId) {
|
||||
userSessionRegistry.removeSession(sessionId);
|
||||
broadcastOnlineUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线用户列表
|
||||
*
|
||||
* @return 在线用户信息列表
|
||||
*/
|
||||
public List<OnlineUserDTO> getOnlineUsers() {
|
||||
return userSessionRegistry.getOnlineUsers();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线用户数量
|
||||
*
|
||||
* @return 在线用户数(不是会话数)
|
||||
*/
|
||||
public int getOnlineUserCount() {
|
||||
return userSessionRegistry.getOnlineUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线会话总数
|
||||
*
|
||||
* @return 所有在线会话的总数
|
||||
*/
|
||||
public int getTotalSessionCount() {
|
||||
return userSessionRegistry.getTotalSessionCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否在线
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 是否在线
|
||||
*/
|
||||
public boolean isUserOnline(String username) {
|
||||
return userSessionRegistry.isUserOnline(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定用户的会话数量
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 会话数量
|
||||
*/
|
||||
public int getUserSessionCount(String username) {
|
||||
return userSessionRegistry.getUserSessionCount(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动触发在线用户数量广播
|
||||
*
|
||||
* 供外部服务(如定时任务)调用
|
||||
*/
|
||||
public void notifyOnlineUsersChange() {
|
||||
log.info("手动触发在线用户数量通知,当前在线用户数:{}", getOnlineUserCount());
|
||||
broadcastOnlineUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 广播在线用户数量变更(内部方法)
|
||||
*/
|
||||
private void broadcastOnlineUserCount() {
|
||||
int count = getOnlineUserCount();
|
||||
webSocketPublisher.publish(WebSocketTopics.TOPIC_ONLINE_COUNT, count);
|
||||
log.debug("✓ 已广播在线用户数量: {}", count);
|
||||
}
|
||||
|
||||
// ==================== 消息推送功能 ====================
|
||||
|
||||
/**
|
||||
* 向所有客户端广播字典更新事件
|
||||
*
|
||||
* @param dictCode 字典编码
|
||||
*/
|
||||
@Override
|
||||
public void broadcastDictChange(String dictCode) {
|
||||
if (dictCode == null || dictCode.isEmpty()) {
|
||||
log.warn("字典编码为空,跳过广播");
|
||||
return;
|
||||
}
|
||||
|
||||
DictChangeEvent event = new DictChangeEvent(dictCode);
|
||||
webSocketPublisher.publish(WebSocketTopics.TOPIC_DICT, event);
|
||||
log.info("✓ 已广播字典变更通知: dictCode={}", dictCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向特定用户发送通知消息
|
||||
*
|
||||
* @param username 目标用户名
|
||||
* @param message 消息内容
|
||||
*/
|
||||
@Override
|
||||
public void sendNotification(String username, Object message) {
|
||||
if (username == null || username.isEmpty()) {
|
||||
log.warn("用户名为空,无法发送通知");
|
||||
return;
|
||||
}
|
||||
|
||||
if (message == null) {
|
||||
log.warn("消息内容为空,无法发送给用户[{}]", username);
|
||||
return;
|
||||
}
|
||||
|
||||
webSocketPublisher.publishToUser(username, WebSocketTopics.USER_QUEUE_MESSAGES, message);
|
||||
log.info("✓ 已向用户[{}]发送通知", username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 广播系统消息给所有用户
|
||||
*
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public void broadcastSystemMessage(String message) {
|
||||
if (message == null || message.isEmpty()) {
|
||||
log.warn("消息内容为空,无法广播");
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> systemMessage = Map.of(
|
||||
"sender", "系统通知",
|
||||
"content", message,
|
||||
"timestamp", System.currentTimeMillis()
|
||||
);
|
||||
webSocketPublisher.publish(WebSocketTopics.TOPIC_PUBLIC, systemMessage);
|
||||
log.info("✓ 已广播系统消息: {}", message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package com.youlai.boot.support.websocket.session;
|
||||
|
||||
import com.youlai.boot.support.websocket.dto.OnlineUserDTO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* WebSocket 用户会话注册表
|
||||
* <p>
|
||||
* 维护WebSocket连接的用户会话信息,支持多设备同时登录。
|
||||
* 采用双Map结构实现高效查询:
|
||||
* <ul>
|
||||
* <li>userSessionsMap: 用户名 -> 会话ID集合(支持多设备)</li>
|
||||
* <li>sessionDetailsMap: 会话ID -> 会话详情(快速定位用户)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Ray.Hao
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserSessionRegistry {
|
||||
|
||||
/**
|
||||
* 用户会话映射表
|
||||
* <p>
|
||||
* Key: 用户名
|
||||
* Value: 该用户所有WebSocket会话ID集合(支持多设备登录)
|
||||
*/
|
||||
private final Map<String, Set<String>> userSessionsMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 会话详情映射表
|
||||
* <p>
|
||||
* Key: WebSocket会话ID
|
||||
* Value: 会话详情(包含用户名、连接时间等)
|
||||
*/
|
||||
private final Map<String, SessionInfo> sessionDetailsMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 用户上线(建立WebSocket连接)
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param sessionId WebSocket会话ID
|
||||
*/
|
||||
public void userConnected(String username, String sessionId) {
|
||||
userSessionsMap.computeIfAbsent(username, k -> ConcurrentHashMap.newKeySet()).add(sessionId);
|
||||
sessionDetailsMap.put(sessionId, new SessionInfo(username, sessionId, System.currentTimeMillis()));
|
||||
log.debug("用户[{}]会话[{}]已注册", username, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户下线(断开所有WebSocket连接)
|
||||
* <p>
|
||||
* 移除该用户的所有会话信息
|
||||
*
|
||||
* @param username 用户名
|
||||
*/
|
||||
public void userDisconnected(String username) {
|
||||
Set<String> sessions = userSessionsMap.remove(username);
|
||||
if (sessions == null) {
|
||||
return;
|
||||
}
|
||||
sessions.forEach(sessionDetailsMap::remove);
|
||||
log.debug("用户[{}]已下线,移除{}个会话", username, sessions.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除指定会话(单设备下线)
|
||||
* <p>
|
||||
* 当用户某一设备断开连接时调用,保留其他设备的会话
|
||||
*
|
||||
* @param sessionId WebSocket会话ID
|
||||
*/
|
||||
public void removeSession(String sessionId) {
|
||||
SessionInfo sessionInfo = sessionDetailsMap.remove(sessionId);
|
||||
if (sessionInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String username = sessionInfo.getUsername();
|
||||
Set<String> sessions = userSessionsMap.get(username);
|
||||
if (sessions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
sessions.remove(sessionId);
|
||||
if (sessions.isEmpty()) {
|
||||
// 该用户没有任何会话了,移除用户记录
|
||||
userSessionsMap.remove(username);
|
||||
log.debug("用户[{}]最后一个会话已移除", username);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线用户数量
|
||||
*
|
||||
* @return 当前在线用户数(非会话数)
|
||||
*/
|
||||
public int getOnlineUserCount() {
|
||||
return userSessionsMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定用户的会话数量
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 该用户的WebSocket会话数量(多设备登录时大于1)
|
||||
*/
|
||||
public int getUserSessionCount(String username) {
|
||||
Set<String> sessions = userSessionsMap.get(username);
|
||||
return sessions != null ? sessions.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线会话总数
|
||||
*
|
||||
* @return 所有WebSocket会话的总数(包含多设备)
|
||||
*/
|
||||
public int getTotalSessionCount() {
|
||||
return sessionDetailsMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否在线
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 是否在线(至少有一个活跃会话)
|
||||
*/
|
||||
public boolean isUserOnline(String username) {
|
||||
Set<String> sessions = userSessionsMap.get(username);
|
||||
return sessions != null && !sessions.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有在线用户列表
|
||||
*
|
||||
* @return 在线用户信息列表
|
||||
*/
|
||||
public List<OnlineUserDTO> getOnlineUsers() {
|
||||
return userSessionsMap.entrySet().stream()
|
||||
.map(entry -> {
|
||||
String username = entry.getKey();
|
||||
Set<String> sessions = entry.getValue();
|
||||
// 取最早的连接时间作为登录时间
|
||||
long earliestLoginTime = sessions.stream()
|
||||
.map(sessionDetailsMap::get)
|
||||
.filter(info -> info != null)
|
||||
.mapToLong(SessionInfo::getConnectTime)
|
||||
.min()
|
||||
.orElse(System.currentTimeMillis());
|
||||
|
||||
return new OnlineUserDTO(username, sessions.size(), earliestLoginTime);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* WebSocket 会话详情(内部使用)
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
private static class SessionInfo {
|
||||
/** 用户名 */
|
||||
private String username;
|
||||
/** WebSocket会话ID */
|
||||
private String sessionId;
|
||||
/** 连接时间戳 */
|
||||
private long connectTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.youlai.boot.support.websocket.topic;
|
||||
|
||||
public final class WebSocketTopics {
|
||||
|
||||
private WebSocketTopics() {
|
||||
}
|
||||
|
||||
public static final String TOPIC_DICT = "/topic/dict";
|
||||
public static final String TOPIC_ONLINE_COUNT = "/topic/online-count";
|
||||
public static final String TOPIC_PUBLIC = "/topic/public";
|
||||
|
||||
public static final String USER_QUEUE_MESSAGES = "/queue/messages";
|
||||
public static final String USER_QUEUE_MESSAGE = "/queue/message";
|
||||
}
|
||||
Reference in New Issue
Block a user