【发布时间】: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