Spring Integration DSL Filter 与带有单个收件人和 DefaultOutputToParentFlow 的 RouteToRecipients

chi*_*z13 5 spring spring-integration spring-boot spring-integration-dsl

当给定的评估返回 false 时,我需要将消息从父流路由到新流,但当该评估返回 true 时,让它继续在父流中。目前我已经能够使用 Spring Integration DSL.filter()方法成功实现此功能,没有任何问题。但是,我觉得.filter()这样使用似乎并不符合该方法的真正意图。是否有某种类型的路由器可以用来更好地实现同样的需求?是否有必要从这种实现更改.filter()为基于路由器的实现?

以下面的集成流程配置为例......

@Bean
public IntegrationFlow flow() {
    return IntegrationFlows
            .from("inboundChannel")
            .filter(someService::someTrueFalseMethod, onFalseReturn -> onFalseReturn.discardChannel("otherFlowInboundChannel"))
            .handle(someService::someHandleMethod)
            .get();
}

@Bean
public IntegrationFlow otherFlow() {
    return IntegrationFlows
            .from("otherFlowInboundChannel")
            .handle(someOtherService::someOtherHandleMethod)
            .get();
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,这似乎.routeToRecipents()可能是我需要使用的。在我的场景中,我需要评估消息的标头,这就是recipientMessageSelector使用它的原因。

@Bean
public IntegrationFlow flow() {
    return IntegrationFlows
            .from("inboundChannel"
            .routeToRecipients(router -> router
                .recipientMessageSelector("otherFlowInboundChannel", someService::someTrueFalseMethod)
                .defaultOutputToParentFlow()
            )
            .handle(someService::someHandleMethod)
            .get();
}

@Bean
public IntegrationFlow otherFlow() {
    return IntegrationFlows
            .from("otherFlowInboundChannel")
            .handle(someOtherService::someOtherHandleMethod)
            .get();
}
Run Code Online (Sandbox Code Playgroud)

即使这个routeToRecipients解决方案似乎有效,它和上面的过滤器实现之间真的有什么好处吗?

Art*_*lan 4

嗯,它实际上不是关于 Java DSL 方法以及如何使用它们的。它实际上是关于这些 IE 模式的理论。

我们来FilterRecipientListRouterEIP对比一下!

过滤器- https://www.enterpriseintegrationpatterns.com/patterns/messaging/Filter.html

如果消息内容与消息过滤器指定的条件匹配,则消息将路由到输出通道。如果消息内容不符合条件,则该消息将被丢弃。

因此,从技术上讲,filter它不符合您的期望,因为在false解决方案时您有点丢弃消息。然而,为了对这些被丢弃的消息进行可能的处理,Spring Integration 提供了一个discardChannel启动丢弃子流的选项。所以,我们可以把它当作if..else建筑......

收件人列表- https://www.enterpriseintegrationpatterns.com/patterns/messaging/RecipientList.html

然后使用收件人列表检查传入消息,确定所需收件人的列表,并将消息转发到与列表中的收件人关联的所有通道。

所以,有点像您所需要的,因为您评估消息和收件人,然后发送到他们的渠道。唯一的问题是模拟一种filter行为,因为您不会有两个以上具有互斥目的的通道。

当该filter方法感觉像是滥用流控制时(提醒我 Java 中的类似逻辑依赖于流控制的异常处理),它并不要求我们始终遵循规范行为,以便在消息不存在时以错误结束符合一个条件。

适用recipientList于更复杂的场景,即选择器用于任意计算,而不仅仅是简单的布尔值,并且能够将相同的消息分发到多个输出通道。因此,我不会推荐它用于这种简单的true/false场景。

您可以考虑研究另一种类似的模式:

基于内容的路由器- https://www.enterpriseintegrationpatterns.com/patterns/messaging/ContentBasedRouter.html

使用基于内容的路由器根据消息内容将每条消息路由到正确的收件人。

这感觉非常接近您所需要的true/false,并且不会滥用错误(丢弃)进行流程控制,并且不会向我们指定收件人列表。defaultOutputToParentFlow()当您想依赖非映射结果时,这个也有这个问题。

恕我直言,我会坚持filter()- 其true/false逻辑,discardChannel它看起来确实像基于内容的路由器的特定实现:-)。