Spring Thymeleaf+WebFlux实现列表变更时UI自动更新问题
解决方案:基于WebSocket实现实时更新连接数
由于你的应用已经大量使用WebSocket,最轻量化的方案是利用现有WebSocket机制,在用户连接/断开时主动推送更新后的连接数到前端,无需页面刷新。
后端修改步骤
1. 在事件监听器中添加消息推送逻辑
注入SimpMessagingTemplate,在用户连接/断开事件触发时,计算最新连接数并推送到指定主题:
import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Component; import org.springframework.web.socket.messaging.SessionConnectEvent; import org.springframework.web.socket.messaging.SessionDisconnectEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component public class WebSocketEventListener { private static final Logger log = LoggerFactory.getLogger(WebSocketEventListener.class); private final SimpUserRegistry simpUserRegistry; private final UserRepository userRepository; private final SimpMessagingTemplate messagingTemplate; // 构造函数注入依赖 public WebSocketEventListener(SimpUserRegistry simpUserRegistry, UserRepository userRepository, SimpMessagingTemplate messagingTemplate) { this.simpUserRegistry = simpUserRegistry; this.userRepository = userRepository; this.messagingTemplate = messagingTemplate; } @EventListener public void onDisconnectEvent(SessionDisconnectEvent event) { log.warn("Client with username {} disconnected", event.getUser().getName()); sendUpdatedUserCount(); } @EventListener public void onConnectedEvent(SessionConnectEvent event) { log.warn("Client with username {} connected", event.getUser().getName()); sendUpdatedUserCount(); } // 推送最新连接数到前端 private void sendUpdatedUserCount() { // 二选一:使用SimpUserRegistry或UserRepository的统计结果 int count = simpUserRegistry.getUserCount(); // int count = userRepository.findByConnectionNotNull().size(); messagingTemplate.convertAndSend("/topic/connectedUsers", "Connected clients: " + count); } }
2. 确保WebSocket配置正确(若未配置)
如果应用还没有WebSocket配置类,添加以下配置启用STOMP协议和消息代理:
import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { // 启用内存消息代理,支持主题推送 config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 注册WebSocket端点,支持SockJS fallback registry.addEndpoint("/ws").withSockJS(); } }
前端Thymeleaf页面修改
在hello.html中添加WebSocket客户端逻辑,订阅主题并实时更新<p>元素:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>Connected Users</title> <!-- 引入SockJS和STOMP客户端库 --> <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/lib/stomp.min.js"></script> </head> <body> <!-- 初始值由后端控制器渲染 --> <p id="connectedUsers" th:text="${message}">Connected clients: 0</p> <script> // 建立WebSocket连接 const socket = new SockJS('/ws'); const stompClient = Stomp.over(socket); // 连接成功后订阅主题 stompClient.connect({}, function(frame) { console.log('WebSocket连接成功: ' + frame); // 订阅连接数更新主题 stompClient.subscribe('/topic/connectedUsers', function(message) { // 更新页面元素内容 document.getElementById('connectedUsers').textContent = message.body; }); }); // 页面关闭时断开WebSocket连接 window.addEventListener('beforeunload', function() { if (stompClient && stompClient.connected) { stompClient.disconnect(); } }); </script> </body> </html>
工作原理
- 页面加载时,后端控制器将初始连接数渲染到
<p>元素中。 - 前端通过SockJS建立WebSocket连接,订阅
/topic/connectedUsers主题。 - 当用户连接或断开时,事件监听器触发,计算最新连接数并通过
SimpMessagingTemplate推送到所有订阅该主题的客户端。 - 前端收到消息后,直接更新
<p>元素内容,无需刷新页面。
这个方案完全复用现有WebSocket基础设施,无需引入WebFlux或其他复杂框架,实现了轻量化的实时更新。
内容的提问来源于stack exchange,提问作者FARS
相关产品推荐
相关产品推荐

