Spring Web套接字消息传递 - 订阅并发送初始消息

时间:2017-02-04 13:16:52

标签: spring stomp spring-websocket spring-messaging

使用Stomp代理中继进行Web套接字消息传递,我可以订阅目标/topic/mydest。这将创建一个代理订阅,并接收系统中某些内容触发此代理目标的所有消息,这种情况发生在系统中的某些事件发生时。

我可以订阅目标/app/mydest,并且将调用带有@SubscribeMapping("mydest")的控制器方法,并且返回值仅作为消息在此套接字上发回。据我所知,这是唯一将为此订阅发送的消息。

有没有办法在单个订阅中组合它,即为某个/topic目的地创建代理订阅,触发一些直接将消息发送回订阅者的代码?

用例:当系统发生错误时,会将具有当前错误计数的消息发送到/topic/mydest。当新客户订阅时,我只想向他发送最后已知的错误计数。其他人对此刻并不感兴趣,因为伯爵没有改变。

我目前的解决方案是订阅/app/mydest/topic/mydest,并在客户端上使用相同的消息处理程序。但它确实是一个逻辑订阅,并且它有点容易出错,因为客户需要记住订阅它们。

我在这方面的问题:是否会有/app/订阅的进一步消息?有没有什么可以触发一个?如何向主机的订户发送初始信息,而不向现有订户发送冗余消息?

根据要求,这是我的Websocket配置类。

@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableStompBrokerRelay("/queue/", "/topic/", "/exchange/");
        registry.setApplicationDestinationPrefixes("/app");
    }
}

2 个答案:

答案 0 :(得分:0)

您可以使用ApplicationListenerSessionSubscribeEvent。 例如:

@Component
public class SubscribeListener implements ApplicationListener<SessionSubscribeEvent> {

    private final SimpMessagingTemplate messagingTemplate;

    @Autowired
    public SubscribeListener(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    @Override
    public void onApplicationEvent(SessionSubscribeEvent event) {
        messagingTemplate.convertAndSendToUser(event.getUser().getName(), "/topic/mydest", "Last known error count");
    }
}

答案 1 :(得分:0)

您可以监听会话订阅事件并发送初始消息

@Component
@RequiredArgsConstructor
public class WebSocketEventListener {

private static final Logger logger = LoggerFactory.getLogger(WebSocketEventListener.class);
private final SimpMessagingTemplate simpMessagingTemplate;


@EventListener
public void handleSessionSubscribeEvent(SessionSubscribeEvent event) {
    logger.info("Subscribed to session: " + event);
    Principal user = event.getUser();
    if (user instanceof UsernamePasswordAuthenticationToken) {
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) user;
        if (token.getPrincipal() instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) token.getPrincipal();
            simpMessagingTemplate.convertAndSendToUser(userDetails.getUsername(), "/queue/notify", "Hello");
        }
    }
}

}