Springboot集成websocket实现聊天场景
本文展示用springboot集成websocket实现聊天场景。点对点聊天与群聊天。
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.7.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
添加配置类
/**
* WebSocket配置类
*
* @author yangfang2
* @date 2024/2/22 10:28
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
编写服务端
-
WebSocketServer类
/** * WebSocket 实现点对点聊天、群聊 * <p> * 每个客户端连接,新生成一个ServerEndpoint实例 * * @author yangfang2 * @date 2024/2/22 10:26 */ @Slf4j @Component @ServerEndpoint("/chat/{sessionId}") public class WebSocketServer { /** * 静态变量(属于类) 记录当前在线连接数 */ private static final AtomicInteger onlineSessionClientCount = new AtomicInteger(0); /** * 静态变量(属于类) 存放在线的客户端 */ private static final Map<String, Session> onlineSessionClientMap = new ConcurrentHashMap<>(); /** * 非静态变量(属于类实例) 当前连接的sessionId */ private String curSessionId; /** * 非静态变量(属于类实例) 当前连接的session */ private Session curSession; /** * 客户端连接成功调用此方法。由前端<code>new WebSocket</code>触发 * * @param sessionId 每次页面建立连接时传入到服务端的id,比如用户id等。可以自定义。 * @param session 与某个客户端的连接会话,需要通过它来给客户端发送消息 */ @OnOpen public void onOpen(@PathParam("sessionId") String sessionId, Session session) { this.curSessionId = sessionId; this.curSession = session; //放入map中 onlineSessionClientMap.put(sessionId, session); //在线客户端数+1 onlineSessionClientCount.incrementAndGet(); //回复消息 sendToOne(sessionId, "连接成功!"); log.info("连接建立成功,当前在线数为:{} ==> 开始监听新连接: sessionId = {}", onlineSessionClientCount, sessionId); } /** * 服务端收到客户端消息后调用的方法。由前端<code>socket.send</code>触发 * 当服务端执行toSession.getAsyncRemote().sendText(xxx)后,前端的socket.onmessage得到监听。 * * @param data 服务端收到的消息 */ @OnMessage public void onMessage(String data) { log.info("服务端收到客户端消息 ==> sessionId = {}, data = {}", curSessionId, data); ChatVo chatVo = JSON.parseObject(data, ChatVo.class); String toSessionId = chatVo.getToSessionId(); String toMessage = chatVo.getToMessage(); if (StringUtils.isBlank(toSessionId)) { //群发 sendToAll(toMessage); } else { //单发 sendToOne(toSessionId, toMessage); } } /** * 发生错误调用的方法 * * @param error 错误 */ @OnError public void onError(Throwable error) throws IOException { log.error("WebSocket发生错误,错误信息为:" + error.getMessage()); //关闭连接 onClose(); } /** * 客户端关闭连接调用的方法。由前端<code>socket.close()</code>触发 */ @OnClose public void onClose() throws IOException { // 从 Map中移除 onlineSessionClientMap.remove(curSessionId); //在线数减1 onlineSessionClientCount.decrementAndGet(); //断开连接 curSession.close(); log.info("连接关闭成功,当前在线数为:{} ==> 关闭该连接信息:sessionId = {}", onlineSessionClientCount, curSessionId); } /** * 发送消息给指定session * * @param toSessionId 接收的sessionId * @param message 接收的消息 */ private void sendToOne(String toSessionId, String message) { Session toSession = onlineSessionClientMap.get(toSessionId); if (Objects.isNull(toSession)) { log.error("服务端给客户端发送消息 ==> toSessionId = {} 不存在, message = {}", toSessionId, message); return; } // 异步发送 log.info("服务端给客户端发送消息 ==> toSessionId = {}, message = {}", toSessionId, message); toSession.getAsyncRemote().sendText(curSessionId + ":" + message); } /** * 发送消息给所有session * * @param message 接收的消息 */ private void sendToAll(String message) { Set<String> allSessionIds = onlineSessionClientMap.keySet(); allSessionIds .stream() //不给自己发 .filter(s -> !Objects.equals(s, curSessionId)) .forEach(toSessionId -> { sendToOne(toSessionId, message); }); } } -
ChatVo类
@Getter @Setter public class ChatVo { /** * 发送的sessionId */ private String toSessionId; /** * 发送的内容 */ private String toMessage; }
使用ApiFox测试

-
新建三个连接
用户1:ws://localhost:8080/chat/user1 并连接到服务端
用户2:ws://localhost:8080/chat/user2 并连接到服务端
用户3:ws://localhost:8080/chat/user3 并连接到服务端

私聊天
- 用户1给用户2发信息

- 用户2收到用户1的消息

- 用户2给用户1回消息

- 用户1收到用户2回的消息

群聊天
- 用户3给所有连接到服务端用户发送消息

- 用户1和用户2都收到用户3的消息


本文详细介绍了如何使用SpringBoot框架和WebSocket技术创建一个支持点对点和群聊的聊天应用,包括依赖导入、配置类设置和服务器端关键方法的实现。
2625

被折叠的 条评论
为什么被折叠?



