【问题标题】:Websocket breaks when the page is reloaded重新加载页面时Websocket中断
【发布时间】:2020-11-09 17:42:58
【问题描述】:

我们有一个 Java 应用程序,它使用 SpringBoot 消息支持通过 websocket 上的 stomp 连接发送消息。一旦他们连接并订阅主题,数据应该发送给特定用户,但是当我们重新加载页面时,websocket 会中断并且不再发送任何消息。

我们在这里监听 SessionSubscribeEvent(所以我们可以在订阅完成后发送初始消息):

@Component
@AllArgsConstructor
public class TransactionSubscriptionListener implements ApplicationListener<SessionSubscribeEvent> {

    private static final String DESTINATION_HEADER = "simpDestination";

    private final RegionTransactionSender regionTransactionSender;

    @Override
    public void onApplicationEvent(SessionSubscribeEvent subscribeEvent) {
        Object simpDestination = subscribeEvent.getMessage().getHeaders().get(DESTINATION_HEADER);
        if (simpDestination == null) {
            return;
        }

        String destination = String.valueOf(simpDestination);

        if (destination.matches(RegionTransactionSender.REGEXP)) {
            regionTransactionSender.send();
        }
    }
}

区域交易发送方实现:

@Component
@AllArgsConstructor
public class RegionTransactionSender {

    public static final String REGEXP =
    ApiVersionConstants.TRANSACTIONS_FOR_REGION_DESTINATION_WITH_SUBSCRIBER + "/\\S*";

    private static final String TOPIC_URL_PREFIX = ApiVersionConstants.TRANSACTIONS_FOR_REGION_DESTINATION + "/";

    private final SimpMessageSendingOperations sendingOperations;

    private final TransactionService transactionService;

    private final SimpUserRegistry simpUserRegistry;

    public void send() {
        Set<SimpUser> users = simpUserRegistry.getUsers();
        users.stream()
            .filter(SimpUser::hasSessions)
            .forEach(this::sendToSubscriptions);
    }

    private void sendToSubscriptions(SimpUser user) {
        user.getSessions().forEach(session -> session.getSubscriptions()
            .forEach(subscription -> sendToTopics(user, subscription)));
    }

    private void sendToTopics(final SimpUser user, final SimpSubscription subscription) {
        String destination = subscription.getDestination();

        if (destination.matches(REGEXP)) {
            Optional<String> regionOptional = WebsocketUtils.retrieveOrganizationRegionFromDestination(destination);
            regionOptional.ifPresent(region -> sendForRegionTopic(user, region));
        }
    }

    private void sendForRegionTopic(final SimpUser user, final String region) {
        Set<TransactionResponse> transactionsForRegion = transactionService
            .getTransactionsForRegion(AbstractWebsocketSender.TRANSACTIONS_COUNT, region);

        sendingOperations.convertAndSendToUser(user.getName(), TOPIC_URL_PREFIX + region, transactionsForRegion);
    }
}

send() 方法稍后会被调用,但不会发送任何消息。

Messages visible in Chrome's network debugging tool

如您所见,我们的其他 websocket (systemBalanceSummary) 运行良好。不同之处在于,在 systemBalanceSummary 上,我们将消息发送到非用户特定的目的地。 还值得一提的是,当我们第一次访问该网站时,一切正常。

为什么当我们重新加载页面时 websocket 会中断?

编辑

经过一些调试,我们发现即使订阅事件被触发,SimpUserRegistry 中也没有用户,但我们不知道是什么原因造成的。

【问题讨论】:

    标签: java spring-boot websocket stomp


    【解决方案1】:

    我已经找到了解决方案。

    首先,您需要实现SimpUserRegistry,而不是使用DefaultSimpUserRegistry。原因是 DefaultSimpUserRegistry 似乎在SessionConnctedEvent 被触发后添加了用户并且它并不总是连接。我改变了这一点,所以在SessionConnectEvent 之后添加了用户。 这解决了重新加载后用户注册表中没有用户的问题。如果这不是问题,您可以跳过它。

    之后我更改了convertAndSendToUser 方法的用法。在问题中提供的代码中,数据被发送到用户名。我改变了它,所以我将数据发送到 sessionId,但也添加了一些标题。这是代码:

    private void sendForRegionTopic(final String region, final String sessionId) {
        Set<TransactionResponse> transactionsForRegion = transactionService
            .getTransactionsForRegion(AbstractWebsocketSender.TRANSACTIONS_COUNT, region);
    
        sendingOperations.convertAndSendToUser(sessionId,
            TOPIC_URL_PREFIX + region,
            transactionsForRegion,
            createHeaders(sessionId));
    }
    
    private MessageHeaders createHeaders(final String sessionId) {
        SimpMessageHeaderAccessor accessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
        accessor.setSessionId(sessionId);
        accessor.setLeaveMutable(true);
    
        return accessor.getMessageHeaders();
    }
    

    【讨论】:

      猜你喜欢
      • 2023-02-05
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      • 2012-05-24
      • 1970-01-01
      相关资源
      最近更新 更多