SpringBoot快速接入WebSocket
pom地址
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
服务端教程
步骤一:服务端Socket设计
本次将用到以下注解:
@Component
:标记为Spring容器@ServerEndpoint
:服务器Socket的地址@OnOpen
:建立连接成功事件标记@OnClose
:建立连接结束事件标记@OnMessage
:接收消息事件
示例程序:
@Slf4j
@Component
@ServerEndpoint("/api/socket/{roomId}")
public class WebSocketServer {
private Integer roomId;
/**
* 建立连接成功
* @param session
* @param userId
*/
@OnOpen
public void onOpen(Session session, @PathParam("roomId") Integer userId) {
this.roomId = userId;
log.info(session.getId());
log.info("roomId: {} 建立连接", userId);
}
@OnClose
public void onClose() {
log.info("连接关闭");
}
@OnMessage
public void onMessage(String message, Session session) {
try {
log.info("message: {}", message);
session.getBasicRemote().sendText("消息已接收");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
步骤二:Configuration自动装配容器
示例程序:
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
效果演示
可以使用网站测试
后端也可以看到:
案例:简易聊天室
@Slf4j
@Component
@ServerEndpoint("/api/socket/{roomId}")
public class WebSocketServer {
// 房间会话映射: roomId -> (sessionId -> Session)
private static final ConcurrentHashMap<Integer, ConcurrentHashMap<String, Session>> roomSessions = new ConcurrentHashMap<>();
// 当前会话的 roomId
private Integer currentRoomId;
@OnOpen
public void onOpen(Session session, @PathParam("roomId") Integer roomId) {
this.currentRoomId = roomId;
roomSessions.computeIfAbsent(roomId, k -> new ConcurrentHashMap<>()).put(session.getId(), session);
log.info("roomId: {} 新连接, 房间连接数: {}", roomId, getRoomSize(roomId));
}
@OnClose
public void onClose(Session session) {
roomSessions.get(currentRoomId).remove(session.getId());
// 清理空房间
if (getRoomSize(currentRoomId) == 0) roomSessions.remove(currentRoomId);
log.info("roomId: {} 连接关闭, 剩余连接: {}", currentRoomId, getRoomSize(currentRoomId));
}
@OnMessage
public void onMessage(String message) {
// 向当前房间广播
broadcastToRoom(currentRoomId, message);
}
// 房间广播方法
public static void broadcastToRoom(Integer roomId, String message) {
ConcurrentHashMap<String, Session> sessions = roomSessions.get(roomId);
if (sessions == null) return;
sessions.forEach((id, session) -> {
if (session.isOpen()) session.getAsyncRemote().sendText(message);
});
}
// 获取房间大小
private static int getRoomSize(Integer roomId) {
return roomSessions.getOrDefault(roomId, new ConcurrentHashMap<>()).size();
}
}
原理:
- 定义了一个线程安全的HashMap存放房间号
- 房间号对应多个Session(会话)
- 定义一个currentRoomId存放当前房间号
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 zxb
评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果