WebSocket实现点对点通信
前面讲到的WebSocket是一种广而告之,任何客户端发送,所有客户端都会收到消息,显然不是所有场景都能满足。有时候需要“群聊”场景,也有时候需要“私聊”场景。
我们需要在原有代码上进行改造:
package org.lzy.test007.websocket;import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import java.util.*;
import java.util.concurrent.ConcurrentHashMap;@Component
public class MyWebSocketHandler extends TextWebSocketHandler {// 保存 userId -> session 映射private final Map<String, WebSocketSession> userSessions = new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) {// 从 URL 参数获取 userIdString query = Objects.requireNonNull(session.getUri()).getQuery(); // userId=10086String userId = null;if (query != null && query.startsWith("userId=")) {userId = query.substring("userId=".length());}if (userId != null) {userSessions.put(userId, session);System.out.println("用户 " + userId + " 已连接");}}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {// 从 URL 参数获取 userIdString query = Objects.requireNonNull(session.getUri()).getQuery(); // userId=10086String userId = null;if (query != null && query.startsWith("userId=")) {userId = query.substring("userId=".length());}WebSocketSession targetSession = userSessions.get(userId);if (targetSession != null && targetSession.isOpen()) {targetSession.sendMessage(new TextMessage("消息: " + message.getPayload() + ",来自" + userId));}}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) {// 移除断开连接的 sessionuserSessions.values().removeIf(s -> s.getId().equals(session.getId()));System.out.println("连接关闭: " + session.getId());}}