对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

从版本 4.1 开始,Spring Integration 提供了路由单企业集成模式的实现。 它作为消息标头实现,用于在未为终结点指定 an 时确定实例中的下一个通道。 此模式在复杂、动态的情况下非常有用,因为此时配置多个路由器以确定消息流可能变得很困难。 当消息到达没有 的端点时,将咨询 以确定消息发送到的下一个通道。 当工艺路线单用完时,恢复正常处理。routingSlipAbstractMessageProducingHandleroutputChanneloutput-channelroutingSlipreplyChannelSpring中文文档

路由单的配置以一个选项的形式呈现,即包含条目的分号分隔的路由单,如以下示例所示:HeaderEnricherpathSpring中文文档

<util:properties id="properties">
    <beans:prop key="myRoutePath1">channel1</beans:prop>
    <beans:prop key="myRoutePath2">request.headers[myRoutingSlipChannel]</beans:prop>
</util:properties>

<context:property-placeholder properties-ref="properties"/>

<header-enricher input-channel="input" output-channel="process">
    <routing-slip
        value="${myRoutePath1}; @routingSlipRoutingPojo.get(request, reply);
               routingSlipRoutingStrategy; ${myRoutePath2}; finishChannel"/>
</header-enricher>

前面的示例包含:Spring中文文档

  • 一种配置,用于演示可以将路由单中的条目指定为可解析键。<context:property-placeholder>pathSpring中文文档

  • 子元素用于将 填充到处理程序。<header-enricher><routing-slip>RoutingSlipHeaderValueMessageProcessorHeaderEnricherSpring中文文档

  • 接受已解析的路由单条目数组,并返回 (from ) a 和 as 和 as 首字母 。RoutingSlipHeaderValueMessageProcessorStringpathprocessMessage()singletonMappathkey0routingSlipIndexSpring中文文档

路由单条目可以包含 Bean 名称、Bean 名称和 Spring 表达式 (SpEL)。 根据第一次调用时检查每个路由单条目。 它将条目(在应用程序上下文中不是 Bean 名称)转换为实例。 条目被多次调用,直到它们返回 null 或空 .pathMessageChannelRoutingSlipRouteStrategyRoutingSlipHeaderValueMessageProcessorpathBeanFactoryprocessMessageExpressionEvaluatingRoutingSlipRouteStrategyRoutingSlipRouteStrategyStringSpring中文文档

由于该过程涉及路由单,因此我们有一个请求-回复上下文。 已引入 来确定下一个使用 和 对象。 此策略的实现应在应用程序上下文中注册为 bean,其 Bean 名称用于路由单。 提供了实现。 它接受 SpEL 表达式,并将内部对象用作评估上下文的根对象。 这是为了避免每次调用的创建开销。 它是一个简单的 Java Bean,具有两个属性:和 。 通过此表达式实现,我们可以使用 SpEL(例如,和 )指定路由单条目,并避免为 .getOutputChannelRoutingSlipRouteStrategyoutputChannelrequestMessagereplypathExpressionEvaluatingRoutingSlipRouteStrategyExpressionEvaluatingRoutingSlipRouteStrategy.RequestAndReplyEvaluationContextExpressionEvaluatingRoutingSlipRouteStrategy.getNextPath()Message<?> requestObject replypath@routingSlipRoutingPojo.get(request, reply)request.headers[myRoutingSlipChannel]RoutingSlipRouteStrategySpring中文文档

参数始终是 . 根据上下文,应答对象可以是 、 或任意应用程序域对象(例如,当它由服务激活器调用的 POJO 方法返回时)。 在前两种情况下,使用 SpEL(或 Java 实现)时,常用属性( 和 )可用。 对于任意域对象,这些属性不可用。 因此,如果结果用于确定下一个路径,则在将路由单与 POJO 方法结合使用时要小心。requestMessageMessage<?>Message<?>AbstractIntegrationMessageBuilderMessagepayloadheaders
参数始终是 . 根据上下文,应答对象可以是 、 或任意应用程序域对象(例如,当它由服务激活器调用的 POJO 方法返回时)。 在前两种情况下,使用 SpEL(或 Java 实现)时,常用属性( 和 )可用。 对于任意域对象,这些属性不可用。 因此,如果结果用于确定下一个路径,则在将路由单与 POJO 方法结合使用时要小心。requestMessageMessage<?>Message<?>AbstractIntegrationMessageBuilderMessagepayloadheaders
如果分布式环境中涉及路由单,我们建议不要对路由单使用内联表达式。 此建议适用于分布式环境(如跨 JVM 应用程序)、使用直通消息代理(如AMQP 支持JMS 支持)或在集成流中使用持久性(消息存储)。 框架用于将它们转换为对象,并在消息标头中使用它们。 由于这个类不是(它不可能是,因为它依赖于 ),因此整个 变得不可序列化,并且在任何分布式操作中,我们最终都会得到一个 . 要克服此限制,请向所需的 SpEL 注册一个 Bean,并在路由单配置中使用其 Bean 名称。pathrequest-replyMessageStoreRoutingSlipHeaderValueMessageProcessorExpressionEvaluatingRoutingSlipRouteStrategyroutingSlipSerializableBeanFactoryMessageNotSerializableExceptionExpressionEvaluatingRoutingSlipRouteStrategypath
如果分布式环境中涉及路由单,我们建议不要对路由单使用内联表达式。 此建议适用于分布式环境(如跨 JVM 应用程序)、使用直通消息代理(如AMQP 支持JMS 支持)或在集成流中使用持久性(消息存储)。 框架用于将它们转换为对象,并在消息标头中使用它们。 由于这个类不是(它不可能是,因为它依赖于 ),因此整个 变得不可序列化,并且在任何分布式操作中,我们最终都会得到一个 . 要克服此限制,请向所需的 SpEL 注册一个 Bean,并在路由单配置中使用其 Bean 名称。pathrequest-replyMessageStoreRoutingSlipHeaderValueMessageProcessorExpressionEvaluatingRoutingSlipRouteStrategyroutingSlipSerializableBeanFactoryMessageNotSerializableExceptionExpressionEvaluatingRoutingSlipRouteStrategypath

对于 Java 配置,您可以将实例添加到 Bean 定义中,如以下示例所示:RoutingSlipHeaderValueMessageProcessorHeaderEnricherSpring中文文档

@Bean
@Transformer(inputChannel = "routingSlipHeaderChannel")
public HeaderEnricher headerEnricher() {
    return new HeaderEnricher(Collections.singletonMap(IntegrationMessageHeaderAccessor.ROUTING_SLIP,
            new RoutingSlipHeaderValueMessageProcessor("myRoutePath1",
                                                       "@routingSlipRoutingPojo.get(request, reply)",
                                                       "routingSlipRoutingStrategy",
                                                       "request.headers[myRoutingSlipChannel]",
                                                       "finishChannel")));
}

当终结点生成回复且尚未定义 no 时,路由单算法的工作方式如下:outputChannelSpring中文文档

  • 用于从路由单列表中获取值。routingSlipIndexpathSpring中文文档

  • 如果值 from 是 ,则用于从 中获取 bean。routingSlipIndexStringBeanFactorySpring中文文档

  • 如果返回的 Bean 是 的实例,则该 Bean 用作下一个 的实例,并且 在回复消息头中递增(路由单条目保持不变)。MessageChanneloutputChannelroutingSlipIndexpathSpring中文文档

  • 如果返回的 bean 是 的实例,并且 it 不返回空 ,则该结果将用作下一个 的 bean 名称。 保持不变。RoutingSlipRouteStrategygetNextPathStringoutputChannelroutingSlipIndexSpring中文文档

  • 如果返回空 或 ,则递增 ,并以递归方式为下一个路由单项调用 。RoutingSlipRouteStrategy.getNextPathStringnullroutingSlipIndexgetOutputChannelFromRoutingSlippathSpring中文文档

  • 如果下一个路由单条目不是 ,则它必须是 的实例。pathStringRoutingSlipRouteStrategySpring中文文档

  • 当超过路由单列表的大小时,算法将移动到标准标头的默认行为。routingSlipIndexpathreplyChannelSpring中文文档