Spring 如何在ConnectableFlux中向订户广播消息

Spring 如何在ConnectableFlux中向订户广播消息,spring,spring-webflux,Spring,Spring Webflux,我是Spring WebFlux新手,我在以下链接中找到了使用Spring WebFlux和Websocket的聊天演示: 根据这篇文章,它说: 该应用程序的关键是将WebSocketSessions连接到一个 另一个这是通过连接的传入消息流来实现的 将每个会话发送到全球发布服务器。另一方面,每节课 订阅全球发布者生成的邮件 反应堆配置: @Bean public UnicastProcessor<Event> eventPublisher(){ r

我是Spring WebFlux新手,我在以下链接中找到了使用Spring WebFlux和Websocket的聊天演示:

根据这篇文章,它说:

该应用程序的关键是将WebSocketSessions连接到一个 另一个这是通过连接的传入消息流来实现的 将每个会话发送到全球发布服务器。另一方面,每节课 订阅全球发布者生成的邮件

反应堆配置:

    @Bean
    public UnicastProcessor<Event> eventPublisher(){
        return UnicastProcessor.create();
    }

    @Bean
    public Flux<Event> events(UnicastProcessor<Event> eventPublisher) {
        return eventPublisher
                .replay(25)
                .autoConnect();
    }

    @Bean
    public HandlerMapping webSocketMapping(UnicastProcessor<Event> eventPublisher, Flux<Event> events) {
        Map<String, Object> map = new HashMap<>();
        map.put("/websocket/chat", new ChatSocketHandler(eventPublisher, events));
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        simpleUrlHandlerMapping.setUrlMap(map);

        //Without the order things break :-/
        simpleUrlHandlerMapping.setOrder(10);
        return simpleUrlHandlerMapping;
    }

    @Bean
    public WebSocketHandlerAdapter handlerAdapter() {
        return new WebSocketHandlerAdapter();
    }
@Bean
公共单播处理器eventPublisher(){
返回UnicastProcessor.create();
}
@豆子
公共流量事件(UnicastProcessor eventPublisher){
返回事件发布者
.重播(25)
.autoConnect();
}
@豆子
public HandlerMapping webSocketMapping(UnicastProcessor eventPublisher,Flux事件){
Map Map=newhashmap();
map.put(“/websocket/chat”,新的ChatSocketHandler(eventPublisher,events));
SimpleRhHandlerMapping SimpleRhHandlerMapping=新的SimpleRhHandlerMapping();
simpleUrlHandlerMapping.setUrlMap(map);
//没有秩序,事情就会破裂:-/
simpleUrlHandlerMapping.setOrder(10);
返回simplerlhandermapping;
}
@豆子
公共WebSocketHandlerAdapter handlerAdapter(){
返回新的WebSocketHandlerAdapter();
}
聊天套接字处理程序:

@Override
public Mono<Void> handle(WebSocketSession session) {
    WebSocketMessageSubscriber subscriber = new WebSocketMessageSubscriber(eventPublisher);
    session.receive()
            .map(WebSocketMessage::getPayloadAsText)
            .map(this::toEvent)
            .subscribe(subscriber::onNext, subscriber::onError, subscriber::onComplete);
    return session.send(outputEvents.map(session::textMessage));
}

private static class WebSocketMessageSubscriber {
    private UnicastProcessor<Event> eventPublisher;
    private Optional<Event> lastReceivedEvent = Optional.empty();

    public WebSocketMessageSubscriber(UnicastProcessor<Event> eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void onNext(Event event) {
        lastReceivedEvent = Optional.of(event);
        eventPublisher.onNext(event);
    }

    public void onError(Throwable error) {
        //TODO log error
        error.printStackTrace();
    }

    public void onComplete() {
        lastReceivedEvent.ifPresent(event -> eventPublisher.onNext(
                Event.type(USER_LEFT)
                        .withPayload()
                        .user(event.getUser())
                        .build()));
    }

}
@覆盖
公共单声道句柄(WebSocketSession会话){
WebSocketMessageSubscriber=新的WebSocketMessageSubscriber(eventPublisher);
session.receive()
.map(WebSocketMessage::getPayloadAsText)
.map(this::toEvent)
.subscribe(订阅方::onNext,订阅方::onError,订阅方::onComplete);
返回session.send(outputEvents.map(session::textMessage));
}
私有静态类WebSocketMessageSubscriber{
专用单播处理器;
private Optional lastReceivedEvent=Optional.empty();
公共WebSocketMessageSubscriber(UnicastProcessor eventPublisher){
this.eventPublisher=eventPublisher;
}
公共void onNext(事件){
lastReceivedEvent=可选。of(事件);
eventPublisher.onNext(事件);
}
公共无效onError(可丢弃错误){
//TODO日志错误
错误。printStackTrace();
}
未完成的公共空间(){
lastReceivedEvent.ifPresent(事件->事件发布者.onNext(
事件类型(用户左)
.withPayload()
.user(event.getUser())
.build());
}
}

如果一个用户发送一条消息,那么其他用户可以看到,因为它会广播给所有用户。但是当我阅读代码时,我不明白ConnectableFlux(事件)是如何向所有web套接字会话发送消息的。我还尝试注释UserStats类的代码,但它仍然正常工作。有人能给我解释一下吗?

通过Websocket将消息从服务器发送到浏览器的代码是:

session.send(outputEvents.map(session::textMessage))
换句话说,无论何时将事件(消息)推送到outputEvents流量上,它都将通过链接到会话的Websocket发送到浏览器

它像广播一样工作的原因是,为每个新WebSocketSession创建的每个WebSocketMessageSubscriber都将接收到的所有内容(从浏览器到服务器)发布到eventPublisher上,从而使其在outputEvents上可见

  public void onNext(Event event) {
    lastReceivedEvent = Optional.of(event);
    eventPublisher.onNext(event);
  }
outputEvents流量在所有WebSocketMessageSubscribers之间共享,通过该流量接收的所有事件通过Websocket发送回浏览器,包括从该Websocket接收的事件

在下图中,“全局消息流”表示outputEvents流量

  public void onNext(Event event) {
    lastReceivedEvent = Optional.of(event);
    eventPublisher.onNext(event);
  }

通过Websocket将消息从服务器发送到浏览器的代码是:

session.send(outputEvents.map(session::textMessage))
换句话说,无论何时将事件(消息)推送到outputEvents流量上,它都将通过链接到会话的Websocket发送到浏览器

它像广播一样工作的原因是,为每个新WebSocketSession创建的每个WebSocketMessageSubscriber都将接收到的所有内容(从浏览器到服务器)发布到eventPublisher上,从而使其在outputEvents上可见

  public void onNext(Event event) {
    lastReceivedEvent = Optional.of(event);
    eventPublisher.onNext(event);
  }
outputEvents流量在所有WebSocketMessageSubscribers之间共享,通过该流量接收的所有事件通过Websocket发送回浏览器,包括从该Websocket接收的事件

在下图中,“全局消息流”表示outputEvents流量

  public void onNext(Event event) {
    lastReceivedEvent = Optional.of(event);
    eventPublisher.onNext(event);
  }