Spring Integration DSL 过滤器与带有单个收件人和 DefaultOutputToParentFlow 的 RouteToRecipients

Posted

技术标签:

【中文标题】Spring Integration DSL 过滤器与带有单个收件人和 DefaultOutputToParentFlow 的 RouteToRecipients【英文标题】:Spring Integration DSL Filter vs. RouteToRecipients w/ single Recipient and DefaultOutputToParentFlow 【发布时间】:2020-05-30 13:37:03 【问题描述】:

当给定评估返回 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();

到目前为止,似乎.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();

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

【问题讨论】:

【参考方案1】:

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

让我们比较一下 EIP 中的 FilterRecipientListRouter

过滤器 - 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 中类似的逻辑依赖于流控制的异常处理)时,它并不要求我们始终保持规范行为以结束消息不符合条件时出错。

The recipientList is for more complicated scenarios when a selector is used for any arbitrary evaluation, not just plain boolean and has an ability to distribute the same message into several output channels.所以,对于这种简单的true/false 场景,我不会推荐它。

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

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

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

这个感觉非常接近您对true/false 的需求,它不会滥用流量控制的错误(丢弃),也不会向我们指定收件人列表。当您想依赖非映射结果时,这个也有defaultOutputToParentFlow()

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

【讨论】:

Artem,感谢您回答中的所有细节。我将仔细研究基于内容的路由器,但我同意所有实现最终都会彼此相似。

以上是关于Spring Integration DSL 过滤器与带有单个收件人和 DefaultOutputToParentFlow 的 RouteToRecipients的主要内容,如果未能解决你的问题,请参考以下文章

Spring Integration DSL 中的路由

使用 spring-integration-dsl 的动态 http 入站网关

Spring Integration DSL:PublishSubscribeChannel 订单

Spring Integration DSL JMS 入站/出站网关

如何将请求标头添加到 outboundGateway spring integration dsl

Spring Integration DSL 变压器