SpringBoot WebSocket 实现单聊、群聊及离线信息处理
本文提供使用 Java Spring Boot 框架实现 WebSocket 单聊和群聊的基本思路和代码示例。
一、单聊实现思路
- 客户端连接 WebSocket,并发送用户信息(用户名、用户 ID 等)到后台。
- 后台将用户信息保存到一个 Map 中,以用户 ID 作为键,WebSocketSession 对象作为值。
- 当有用户发送消息时,后台根据接收者的用户 ID 从 Map 中获取 WebSocketSession 对象,并通过该对象发送消息。
- 后台可以保存每个用户的未读消息数量,在用户连接 WebSocket 时将未读消息数量返回给客户端,在客户端打开聊天窗口时将未读消息数量清零。
二、群聊实现思路
- 客户端连接 WebSocket,并发送用户信息(用户名、用户 ID、加入的群聊 ID 等)到后台。
- 后台将用户信息保存到两个 Map 中:一个以用户 ID 作为键,WebSocketSession 对象作为值;另一个以群聊 ID 作为键,保存所有加入该群聊的用户 ID。
- 当有用户发送消息时,后台根据群聊 ID 从 Map 中获取所有加入该群聊的用户 ID,然后根据每个用户 ID 从第一个 Map 中获取 WebSocketSession 对象,并通过该对象发送消息。
- 后台可以保存每个用户在每个群聊中的未读消息数量,在用户连接 WebSocket 时将未读消息数量返回给客户端,在客户端打开聊天窗口时将未读消息数量清零。
三、离线信息处理
- 当用户连接 WebSocket 时,后台可以检查该用户是否有未读消息。如果有,将未读消息发送给客户端。
- 当用户断开 WebSocket 连接时,后台可以将该用户的未读消息保存到数据库或缓存中,等用户下次连接 WebSocket 时再将未读消息发送给客户端。
四、未读信息统计
- 对于单聊,后台可以保存每个用户的未读消息数量,并在用户连接 WebSocket 时将未读消息数量返回给客户端,在客户端打开聊天窗口时将未读消息数量清零。
- 对于群聊,后台可以保存每个用户在每个群聊中的未读消息数量,并在用户连接 WebSocket 时将未读消息数量返回给客户端,在客户端打开聊天窗口时将未读消息数量清零。
代码示例
1. 单聊
@Controller
public class WebSocketController {
// 保存用户 ID 和 WebSocketSession 对象的 Map
private static Map<String, WebSocketSession> users = new ConcurrentHashMap<>();
// 保存每个用户的未读消息数量的 Map
private static Map<String, Integer> unreadMsgCounts = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(WebSocketSession session) throws IOException {
// 获取用户信息
String userId = getUserIdFromSession(session);
// 将用户信息保存到 Map 中
users.put(userId, session);
// 返回该用户的未读消息数量
int unreadMsgCount = unreadMsgCounts.getOrDefault(userId, 0);
session.sendMessage(new TextMessage(String.valueOf(unreadMsgCount)));
// 将未读消息数量清零
unreadMsgCounts.put(userId, 0);
}
@OnMessage
public void onMessage(WebSocketSession session, String message) throws IOException {
// 获取发送者和接收者的用户 ID
String[] parts = message.split(',');
String senderId = getUserIdFromSession(session);
String receiverId = parts[0];
// 获取接收者的 WebSocketSession 对象
WebSocketSession receiverSession = users.get(receiverId);
if (receiverSession != null) {
// 如果接收者在线,直接发送消息
TextMessage msg = new TextMessage(senderId + ',' + parts[1]);
receiverSession.sendMessage(msg);
} else {
// 如果接收者离线,将消息保存到数据库或缓存中
saveOfflineMsg(senderId, receiverId, parts[1]);
// 增加接收者的未读消息数量
int count = unreadMsgCounts.getOrDefault(receiverId, 0);
unreadMsgCounts.put(receiverId, count + 1);
}
}
@OnClose
public void onClose(WebSocketSession session) {
// 移除用户信息
String userId = getUserIdFromSession(session);
users.remove(userId);
}
private String getUserIdFromSession(WebSocketSession session) {
// 从 WebSocketSession 对象中获取用户 ID
// ...
}
private void saveOfflineMsg(String senderId, String receiverId, String content) {
// 将离线消息保存到数据库或缓存中
// ...
}
}
2. 群聊
@Controller
public class WebSocketController {
// 保存用户 ID 和 WebSocketSession 对象的 Map
private static Map<String, WebSocketSession> users = new ConcurrentHashMap<>();
// 保存群聊 ID 和所有加入该群聊的用户 ID 的 Map
private static Map<String, Set<String>> groups = new ConcurrentHashMap<>();
// 保存每个用户在每个群聊中的未读消息数量的 Map
private static Map<String, Map<String, Integer>> unreadMsgCounts = new ConcurrentHashMap<>();
@OnOpen
public void onOpen(WebSocketSession session) throws IOException {
// 获取用户信息
String userId = getUserIdFromSession(session);
String groupId = getGroupIdFromSession(session);
// 将用户信息保存到 Map 中
users.put(userId, session);
Set<String> groupUsers = groups.getOrDefault(groupId, new HashSet<>());
groupUsers.add(userId);
groups.put(groupId, groupUsers);
// 返回该用户在该群聊中的未读消息数量
int unreadMsgCount = unreadMsgCounts.getOrDefault(userId, new HashMap<>()).getOrDefault(groupId, 0);
session.sendMessage(new TextMessage(String.valueOf(unreadMsgCount)));
// 将未读消息数量清零
Map<String, Integer> groupUnreadMsgCounts = unreadMsgCounts.getOrDefault(userId, new HashMap<>());
groupUnreadMsgCounts.put(groupId, 0);
unreadMsgCounts.put(userId, groupUnreadMsgCounts);
}
@OnMessage
public void onMessage(WebSocketSession session, String message) throws IOException {
// 获取发送者和群聊 ID
String[] parts = message.split(',');
String senderId = getUserIdFromSession(session);
String groupId = parts[0];
Set<String> groupUsers = groups.getOrDefault(groupId, new HashSet<>());
// 遍历群聊中所有用户,将消息发送给在线用户,将离线消息保存到数据库或缓存中
for (String userId : groupUsers) {
WebSocketSession receiverSession = users.get(userId);
if (receiverSession != null) {
// 如果接收者在线,直接发送消息
TextMessage msg = new TextMessage(senderId + ',' + parts[1]);
receiverSession.sendMessage(msg);
} else {
// 如果接收者离线,将消息保存到数据库或缓存中
saveOfflineMsg(senderId, userId, groupId, parts[1]);
// 增加接收者在该群聊中的未读消息数量
Map<String, Integer> groupUnreadMsgCounts = unreadMsgCounts.getOrDefault(userId, new HashMap<>());
int count = groupUnreadMsgCounts.getOrDefault(groupId, 0);
groupUnreadMsgCounts.put(groupId, count + 1);
unreadMsgCounts.put(userId, groupUnreadMsgCounts);
}
}
}
@OnClose
public void onClose(WebSocketSession session) {
// 移除用户信息
String userId = getUserIdFromSession(session);
String groupId = getGroupIdFromSession(session);
users.remove(userId);
Set<String> groupUsers = groups.getOrDefault(groupId, new HashSet<>());
groupUsers.remove(userId);
groups.put(groupId, groupUsers);
}
private String getUserIdFromSession(WebSocketSession session) {
// 从 WebSocketSession 对象中获取用户 ID
// ...
}
private String getGroupIdFromSession(WebSocketSession session) {
// 从 WebSocketSession 对象中获取群聊 ID
// ...
}
private void saveOfflineMsg(String senderId, String receiverId, String groupId, String content) {
// 将离线消息保存到数据库或缓存中
// ...
}
}
注意: 以上代码示例仅供参考,实际应用中需要根据具体需求进行修改和完善。
原文地址: http://www.cveoy.top/t/topic/nJac 著作权归作者所有。请勿转载和采集!