如何获取STOMP已连接会话列表?Spring代码获取失败问题
SimpUserRegistry.getUserCount()统计的是经过认证关联的用户会话数,你用Chrome APIC扩展连接时,没有在STOMP连接过程中提供用户身份信息,Spring无法将该WebSocket会话关联到任何SimpUser对象,所以返回0。
注意:日志里的WebSocketSession[2 current WS(2)]是底层的WebSocket连接数,和SimpUserRegistry的统计维度完全不同——前者只要建立了WebSocket连接就算,后者必须是关联了认证用户的会话才会被统计。
方案1:通过自定义拦截器关联用户标识(无需完整认证)
如果不需要严格的用户认证,只是想让SimpUserRegistry统计所有连接,可以自定义握手拦截器,在握手时为每个连接设置一个匿名用户标识:
1.1 实现HandshakeInterceptor
@Component public class StompUserHandshakeInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { // 示例从URL参数获取用户标识,也可从请求头、Cookie等地方取 ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; String username = servletRequest.getServletRequest().getParameter("username"); // 未传username则生成唯一匿名标识 if (username == null) { username = "anonymous-" + UUID.randomUUID(); } // 创建匿名认证对象绑定到会话属性 Authentication auth = new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList()); attributes.put("user", auth); return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { // 无需处理 } }
1.2 注册拦截器到WebSocket配置
修改你的WebSocketConfiguration,添加拦截器:
@EnableWebSocketMessageBroker @Configuration @RequiredArgsConstructor public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer { private final StompUserHandshakeInterceptor handshakeInterceptor; @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/my-chat") .setAllowedOriginPatterns("*") .addInterceptors(handshakeInterceptor); // 注册自定义拦截器 } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.setApplicationDestinationPrefixes("/pub"); registry.enableSimpleBroker("/sub"); } }
1.3 客户端连接时携带标识(可选)
用APIC扩展连接时,可在URL后拼接参数:ws://localhost:8080/my-chat?username=test-user,拦截器会使用指定用户名;若不拼接,会自动生成匿名用户名。此时SimpUserRegistry.getUserCount()就能正确统计连接数。
方案2:直接统计底层WebSocket连接数
如果只是想获取所有已建立的STOMP连接数(不管是否认证),可以直接注入WebSocketMessageBrokerStats来获取:
@Autowired private WebSocketMessageBrokerStats webSocketMessageBrokerStats; @Scheduled(fixedRate = 1000) public void getConnectedUserSessions() { // 获取当前活跃的WebSocket会话数,和日志里的WS数值一致 int currentSessions = webSocketMessageBrokerStats.getWebSocketSessionStats().getCurrentSessionCount(); System.out.println("当前活跃STOMP连接数:" + currentSessions); }
方案3:使用Spring Security完成用户认证
如果系统需要严格的用户认证,可以配置Spring Security,让客户端在连接时携带认证信息(比如JWT令牌、Basic Auth)。Spring会自动将认证通过的用户关联到SimpUserRegistry,此时getUserCount()会返回已认证用户的会话数。
内容的提问来源于stack exchange,提问作者Viper

