不能使用'订阅'或者' subscribeWith'使用' ReactorNettyWebSocketClient'在Kotlin

时间:2018-03-31 17:06:04

标签: websocket kotlin spring-webflux project-reactor

下面的Kotlin代码成功连接到Spring WebFlux服务器,发送消息并打印通过返回的流发送的每条消息。

fun main(args: Array<String>) {
    val uri = URI("ws://localhost:8080/myservice")
    val client = ReactorNettyWebSocketClient()

    val input = Flux.just(readMsg())

    client.execute(uri) { session ->
        session.send(input.map(session::textMessage))
            .thenMany(
                session.receive()
                    .map(WebSocketMessage::getPayloadAsText)
                    .doOnNext(::println) // want to replace this call
                    .then()
            ).then()

    }.block()
}

在之前的反应式编程经验中,我一直使用订阅 subscribeWith ,其中会发生对 doOnNext 的调用。但是在这种情况下它不起作用。我知道这是因为两者都没有返回正在使用的反应流 - 订阅返回一次性 subscribeWith 返回订阅者它作为参数收到。

我的问题是,调用 doOnNext 是否真的是添加处理程序来处理传入邮件的正确方法? 大多数Spring 5教程都会显示调用此函数或日志的代码,但有些使用 subscribeWith(输出).then()而不指定输出应该是什么是。我看不出后者如何编译。

2 个答案:

答案 0 :(得分:1)

subscribesubscribeWith应始终在运算符链的末尾使用,而不是作为中间运算符使用。

答案 1 :(得分:0)

Simon已经提供了答案,但我会添加一些额外的内容。

在将异步逻辑与Reactor(和ReactiveX模式)组合在一起时,您将构建端对端的处理步骤链,其中不仅包括functionsMap.Add(1, () => function1()); functionsMap.Add(3, () => function3()); //etc. 本身的逻辑,还包括底层WebSocket框架代码的逻辑。负责向套接字发送消息和从套接字接收消息。将整个链连接在一起非常重要,因此在运行时,“信号”将从头到尾流过它(onNext,onError或onComplete)并传达最终结果,即您拥有{{1} }。

对于WebSocket,这看起来有些令人生畏,因为您实际上是将两个或多个流组合为一个。您不能只订阅其中一个流(例如用于入站消息),因为这会阻止组成一个统一的处理流,并且信号不会流到预期最终结果的末尾。

另一方面,Action<T>, Func<T1, T2>会触发流的消耗,而您真正想要的是保持延迟模式下构成异步逻辑,即声明在实现数据时将发生的所有事情。这是组成单个统一链很重要的另一个原因。因此可以在完全声明之后触发它。

简而言之,与Servlet世界中命令式WebSocketHandler的主要区别在于,它不是用于处理单个消息的处理程序,而是用于组成完整流的处理程序。在这里,单个消息的处理只是整个处理链的一个步骤。因此,唯一的订阅位置位于.block()的最后,以便开始处理。

顺便说一句,自几个月前首次发布此问题以来,有关如何实现subscribe()的文档已改进为provide more guidance