You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

工作原理

  1. 页面加载时,后端控制器将初始连接数渲染到<p>元素中。
  2. 前端通过SockJS建立WebSocket连接,订阅/topic/connectedUsers主题。
  3. 当用户连接或断开时,事件监听器触发,计算最新连接数并通过SimpMessagingTemplate推送到所有订阅该主题的客户端。
  4. 前端收到消息后,直接更新<p>元素内容,无需刷新页面。

这个方案完全复用现有WebSocket基础设施,无需引入WebFlux或其他复杂框架,实现了轻量化的实时更新。

内容的提问来源于stack exchange,提问作者FARS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:07:22