💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
点对点通信就像是私聊。websocket 实现点对点通信可以采用三种方式来实现。 <br/> 下面分别用三种方法来实现 zhangsan 与 lisi 的私聊。 [TOC] # 1. convertAndSend方法实现 步骤如下: **1. 调用方法convertAndSend** ```java @RestController public class TestController { @Autowired private SimpMessagingTemplate messagingTemplate; @MessageMapping("/v5/point") public void pointChat01(Map<String, Object> params) { //关键点就是订阅地址需要是动态的 messagingTemplate.convertAndSend("/topic/v5/chat/" + params.get("to"), params.get("message")); } } ``` **2. 前端代码** ```js //订阅地址是:/topic/v5/chat/lisi,下面发送时传入了 'to':'lisi' 到后端组成了该地址 client.subscribe('/topic/v5/chat/lisi', (res) => {}) client.send('/app/v5/point', {}, JSON.stringify({'to':'lisi', 'message':'你好,李四.'})) ``` <br/> # 2. @SendToUser实现 步骤如下: **1. 配置类中设置setUserDestinationPrefix** ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/endpoint-websocket") .setAllowedOrigins("*") .withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); //点对点通信时客户端需要添加的前缀,不设置默认为/user registry.setUserDestinationPrefix("/users/"); } } ``` **2. 方法上标注注解`@SendToUser`** ```java @RestController public class TestController { @Autowired private SimpMessagingTemplate messagingTemplate; /** * 缺点就是订阅地址是死的,zhangsan发送消息给lisi,则必须有一个@SendToUser("/topic/v6/lisi")方法 * 反过来又必须有一个 @SendToUser("/topic/v6/zhangsan") 的方法。 */ @MessageMapping("/v6/point") @SendToUser("/topic/v6/lisi") public String pointChat02(String message) { return message; } } ``` **3. 前端代码** ```js //添加了前缀 /users client.subscribe('/users/topic/v6/lisi', (res) => {}) client.send('/app/v6/point', {}, '你好,李四.') ``` <br/> # 3. convertAndSendToUser方法实现 步骤如下: **1. 配置类中设置setUserDestinationPrefix** ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/endpoint-websocket") .setAllowedOrigins("*") .withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); //点对点通信时客户端需要添加的前缀,不设置默认为/user registry.setUserDestinationPrefix("/users/"); } } ``` **2. 存储用户连接的sessionId** ```java @Component public class ConnectListener implements ApplicationListener<SessionConnectEvent> { @Override public void onApplicationEvent(SessionConnectEvent event) { StompHeaderAccessor header = StompHeaderAccessor.wrap(event.getMessage()); //下面将通过前端传递一个key为userId的请求头 String userId = header.getFirstNativeHeader("userId"); String sessionId = header.getSessionId(); //UserConstants.usersMap是我自己创建的一个public static Map对象,用来存储每个用户的sessionId UserConstants.usersMap.put(userId, sessionId); } } ``` **3. 调用方法convertAndSendToUser** ```java @RestController public class TestController { @Autowired private SimpMessagingTemplate messagingTemplate; /** * 方法 convertAndSendToUser(String user, String destination, Object payload, @Nullable Map<String, Object> headers) * user:用户的sessionId * destination:订阅地址 * payload:订阅的数据 * headers:请求头 */ @MessageMapping("/v7/point") public void pointChat03(Map<String, Object> params) { String sessionId = UserConstants.usersMap.get((String) params.get("userId")); SimpMessageHeaderAccessor header = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE); //把sessionId放到请求头中 header.setSessionId(sessionId); header.setLeaveMutable(true); //必须以配置类中的 registry.enableSimpleBroker("/topic") 注册的 /topic 为前缀 messagingTemplate.convertAndSendToUser(sessionId, "/topic/message", "你好,李四!", header.getMessageHeaders()); } } ``` **4. 前端代码** ```js //前端连接的时候传入key为userId的请求头 client.connect({'userId': 'lisi'}, () => { //订阅地址添加 /users 为前缀 client.subscribe('/users/topic/message', (res) => {}) }) //这里我也传了 userId 去与后端匹配 client.send('/app/v7/point', {}, JSON.stringify({'userId': 'lisi', 'message': '你好,李四.'})) ```