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 如何根据项目反应器中的当前可观测值动态选择变换函数?_Kotlin_Reactive Programming_Spring Webflux_Project Reactor - Fatal编程技术网

Kotlin 如何根据项目反应器中的当前可观测值动态选择变换函数?

Kotlin 如何根据项目反应器中的当前可观测值动态选择变换函数?,kotlin,reactive-programming,spring-webflux,project-reactor,Kotlin,Reactive Programming,Spring Webflux,Project Reactor,您好,亲爱的反应式程序员,我开始学习ProjectReactor,但我仍然很难弄清楚何时使用哪个操作符。我发现,如果我想用可重复使用的部件来定义反应器流,我可以使用变换操作符。我想要实现的是基于当前可观察上下文使用这种流函数的特定实现。对于Mono flow,我想到了这个,但我非常不确定它是否是一个好的解决方案: 这是流程的一部分 class CloudeventOverDelegatorRoute( val fromHttpToDelegatorRoute: FromHttpToDeleg

您好,亲爱的反应式程序员,我开始学习ProjectReactor,但我仍然很难弄清楚何时使用哪个操作符。我发现,如果我想用可重复使用的部件来定义反应器流,我可以使用变换操作符。我想要实现的是基于当前可观察上下文使用这种流函数的特定实现。对于Mono flow,我想到了这个,但我非常不确定它是否是一个好的解决方案:

这是流程的一部分

class CloudeventOverDelegatorRoute(
  val fromHttpToDelegatorRoute: FromHttpToDelegatorRoute,
  val delegatorProvider: DelegatorProvider,
  val fromDelegatorToHttpRoute: FromDelegatorToHttpRoute
): MessageRoute<HttpBaseMessage, HttpResponseMessage> {

  override fun isHandlerFor(context: RouteContext): Boolean {
    return fromHttpToDelegatorRoute.isHandlerFor(context)
      && fromDelegatorToHttpRoute.isHandlerFor(context)
  }

  override fun buildPipeline(input: Mono<RoutableMessage<HttpBaseMessage>>): Mono<RoutableMessage<HttpResponseMessage>> {
    var dynamicallyDeterminedDelegator: Delegator? = null
    return input.transform {
      fromHttpToDelegatorRoute.buildPipeline(input)
    }.handle<RoutableMessage<InternalMessage>> { t, u ->
      dynamicallyDeterminedDelegator = delegatorProvider.provideDelegatorFor(t.routeContext)
      u.next(t)
      u.complete()
    }.transform {
      dynamicallyDeterminedDelegator!!.sendDelegated(it)
    }.transform { fromDelegatorToHttpRoute.buildPipeline(it) }
  }

}
class CloudeventOverDelegatorRoute(
val fromHttpToDelegatorRoute:fromHttpToDelegatorRoute,
val delegatorProvider:delegatorProvider,
val fromDelegatorToHttpRoute:fromDelegatorToHttpRoute
):MessageRoute{
override fun isHandlerFor(上下文:RouteContext):布尔值{
从HttpToDelegatorRoute.isHandlerFor返回(上下文)
&&fromDelegatorToHttpRoute.isHandlerFor(上下文)
}
覆盖管道(输入:Mono):Mono{
变量dynamicallyDeterminedDelegator:Delegator?=null
返回input.transform{
从HttpToDelegatorRoute.buildPipeline(输入)
}.handle{t,u->
dynamicallyDeterminedDelegator=delegatorProvider.ProviderDelegatorfor(t.routeContext)
u、 下一个(t)
u、 完成()
}.变换{
dynamicallyDeterminedDelegator!!.sendDelegated(it)
}.transform{fromDelegatorToHttpRoute.buildPipeline(it)}
}
}
这里是动态选择逻辑

interface DelegatorProvider {

  fun provideDelegatorFor(context: RouteContext): Delegator

}

class FirstMatchDelegatorProvider(
  private val delegators: List<Delegator>
): DelegatorProvider {

  override fun provideDelegatorFor(context: RouteContext): Delegator {
    return delegators.firstOrNull {
      it.isHandlerFor(context)
    }?: throw IllegalStateException("No Delegator route available for context: $context")
  }

}
接口委托器提供程序{
提供的乐趣Delegatorfor(上下文:RouteContext):Delegator
}
类FirstMatchDelegatorProvider(
私人val授权人:列表
):委托人提供程序{
覆盖提供的Delegatorfor(上下文:RouteContext):Delegator{
返回授权人。firstOrNull{
it.isHandlerFor(上下文)
}?:抛出IllegalStateException(“没有可用于上下文的委托器路由:$context”)
}
}
这是一个委托人,它提供了整个流程的一个重要的子部分

interface Delegator {

  fun isHandlerFor(context: RouteContext): Boolean

  fun sendDelegated(input: Mono<RoutableMessage<InternalMessage>>): Mono<RoutableMessage<InternalStatusMessage>>

}
接口委托人{
fun isHandlerFor(上下文:RouteContext):布尔值
单声道(输入:单声道):单声道
}

你觉得怎么样?您将如何解决此问题?

此方法存在问题,因为它依赖于共享状态(
dynamicallyDeterminedDelegator
变量)。如果多个订阅者订阅返回的
Mono
,他们可能会覆盖彼此的委托人。也许(多个订阅)不会发生在您的应用程序中,但在任何情况下,这都是一个非常坏的习惯

看起来您可以从
可路由消息
中派生出一个
委托人
,并且您实际上不需要保留该委托人

一次性解析并将delegator应用于routableMessage的最简单方法就是使用
flatMap
。请参阅下面的(伪)java代码:

.flatMap(routableMessage -> {
    val delegator = delegatorProvider.provideDelegatorFor(routableMessage.routeContext);
    return delegator.sendDelegated(routableMessage);
})

您好@Simon,谢谢您指出这一点,特别是delegator完全依赖于RoutableMessage状态。我仍然有一些麻烦,我的头围绕组装和处理时间,但我正在到达那里:)。我最终得到了一个平面贴图解决方案。