Kotlin 如何根据项目反应器中的当前可观测值动态选择变换函数?
您好,亲爱的反应式程序员,我开始学习ProjectReactor,但我仍然很难弄清楚何时使用哪个操作符。我发现,如果我想用可重复使用的部件来定义反应器流,我可以使用变换操作符。我想要实现的是基于当前可观察上下文使用这种流函数的特定实现。对于Mono flow,我想到了这个,但我非常不确定它是否是一个好的解决方案: 这是流程的一部分Kotlin 如何根据项目反应器中的当前可观测值动态选择变换函数?,kotlin,reactive-programming,spring-webflux,project-reactor,Kotlin,Reactive Programming,Spring Webflux,Project Reactor,您好,亲爱的反应式程序员,我开始学习ProjectReactor,但我仍然很难弄清楚何时使用哪个操作符。我发现,如果我想用可重复使用的部件来定义反应器流,我可以使用变换操作符。我想要实现的是基于当前可观察上下文使用这种流函数的特定实现。对于Mono flow,我想到了这个,但我非常不确定它是否是一个好的解决方案: 这是流程的一部分 class CloudeventOverDelegatorRoute( val fromHttpToDelegatorRoute: FromHttpToDeleg
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状态。我仍然有一些麻烦,我的头围绕组装和处理时间,但我正在到达那里:)。我最终得到了一个平面贴图解决方案。