websocket点对点对话、分布式wobsocket实现

整体采用了redis的发布订阅的功能
1.定义了一个由@ServerEndpoint(类似于RequestMapping)的ChatWebSocket类,要让系统知道这个类是端点即通信的服务端,还要定义一个WebSocketConfig配置类,里面定义了一个Bean,serverEndpointExporter,它的作用是当springboot启动完之后,它就会去扫描有@ServerEndpoint注解的bean。
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
ChatWebSocket类中有一个seesion变量,它是一个管道,所有的通信都是基于它来完成的,这个类实现了由@OnMessage和@Open标注的方法,当client1和服务端建立连接时,就会触发@Open标注的方法,会把传进来的userId和seesion,保存到ChatWebSocket的变量userId和session,并且会将当前用户的id和当前的ChatWebSocket对象存到一个静态变量clients中,
当client1发送消息时,触发@OnMessage标注的方法,这时会基于redis将channel和传进来的message("{"receiverId":""+selectCardUserId+"","type": 1, "senderId":""+me.userId+"", "message": ""+content+""}";)发布出去。
2.定义一个监听类RedisChatMessageListener实现了MessageListener接口,当有消息发布时,就能监听到,并且在重写的onMessage方法通过反序列化就能获取发布的到channel和message,然后把消息加到了一个阻塞队列中。
在这个类中还定义了一个消费消息的方法,从队列中把消息取出来,最后取出这个机器上的所有人的连接(ChatWebSocket中的clients),如果有和我们要发送的人即receiverId一样的userId,就从服务端把组装后的信息通过session.getAsyncRemote().sendText(message);发送到客户端,这里有一个点session因为是有状态的,所以我们在判断完clients中的userId有一样的后,还要判断session不为null且状态是open状态。

最后还要加个心跳检测,即客户端发送心跳信息到服务端,我们直接在ChatWebSocket中的@OnMessage和@Open标注的方法,用session.getAsyncRemote().sendText(message);发送一个ok到客户端。
连接关闭的话,就执行@Onclose标注的方法,并将userId从clients中去掉。

posted @ 2025-08-21 23:11  妳似竹  阅读(25)  评论(0)    收藏  举报