Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法在Kotlin中将“subscribe”或“subscribeWith”与“ReactorNettyWebSocketClient”一起使用_Websocket_Kotlin_Spring Webflux_Project Reactor - Fatal编程技术网

无法在Kotlin中将“subscribe”或“subscribeWith”与“ReactorNettyWebSocketClient”一起使用

无法在Kotlin中将“subscribe”或“subscribeWith”与“ReactorNettyWebSocketClient”一起使用,websocket,kotlin,spring-webflux,project-reactor,Websocket,Kotlin,Spring Webflux,Project Reactor,下面的Kotlin代码成功连接到SpringWebFlux服务器,发送消息并打印通过返回的流发送的每条消息 fun main(args: Array<String>) { val uri = URI("ws://localhost:8080/myservice") val client = ReactorNettyWebSocketClient() val input = Flux.just(readMsg()) client.execute(ur

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

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()
}
在以前的反应式编程经验中,我总是在调用doOnNext时使用subscribe或subscribeWith。但是,在这种情况下,它将不起作用。我理解这是因为两者都不返回正在使用的反应流-subscribe返回一个一次性的,subscribeWith返回它作为参数接收的订阅者

我的问题是调用doOnNext是否真的是添加处理程序来处理传入消息的正确方法?
大多数Spring5教程都显示了调用this或log的代码,但有些使用SubscribeWizThoutput.then,但没有指定输出应该是什么。我看不出后者是如何编译的。

subscribe和subscribeWith应该总是在操作符链的末尾使用,而不是作为中间操作符。

Simon已经给出了答案,但我将添加一些额外的上下文

在使用Reactor和ReactiveX模式组合异步逻辑时,您构建了一个端到端的处理步骤链,其中不仅包括WebSocketHandler本身的逻辑,还包括负责向套接字发送和接收消息的底层WebSocket框架代码的逻辑。将整个链连接在一起是非常重要的,这样在运行时,信号将从开始到结束通过onNext、onError或onComplete,并传达最终结果,即在末尾有.block的位置

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

另一方面,subscribe会触发流上的消费,而您真正想要的是保持以延迟模式编写异步逻辑,即声明当数据具体化时将发生的所有事情。这也是为什么组成一个统一的链很重要的另一个原因。因此,它可以在完全声明后触发

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


顺便说一句,自从几个月前第一次发布这个问题以来,文档已经改进为关于如何实现WebSocketHandler。

您有这样的示例吗?给您。。。这就是我的意思。我想指定将对WebSocketMessage的有效负载执行的最终操作。到目前为止,在我对Rx的所有使用中,“subscribe”或“subscribeWith”将是合适的选择,但在这里它似乎必须是“doOnNext”。因此我想问,为什么我想做的最后一件事不符合运营商链的末端条件?啊,明白了。在reactor netty API中,您的最终处理实际上是一个更大链的一部分,该链包含了服务器生命周期的更多部分。这就是为什么您必须返回Flux或Publisher,因此不能使用subscribe。在SpringWebFlux中也是一样,框架订阅了它。我想它一定是这样的。但这似乎明显违反了“最小意外原则”——因为这是API交给我的一个流,我有一个要执行的终端操作。至少我希望能找到更清晰的文档。