路由单

从版本4.1开始,Spring Integration提供了路由表企业集成模式的实现。它作为routingSlip消息头实现,用于在未为端点指定outputChannel时,在AbstractMessageProducingHandler实例中确定下一个通道。当消息流的配置变得复杂和动态时,需要配置多个路由器来确定消息流,此模式非常有用。当消息到达没有output-channel的端点时,会查阅routingSlip以确定消息发送到的下一个通道。当路由表耗尽时,正常的replyChannel处理将恢复。

路由表的配置表示为HeaderEnricher选项——一个以分号分隔的路由表,其中包含path条目,如以下示例所示

<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>

前面的例子有

  • 一个<context:property-placeholder>配置,演示路由表path中的条目可以指定为可解析的键。

  • <header-enricher><routing-slip>子元素用于将RoutingSlipHeaderValueMessageProcessor填充到HeaderEnricher处理器。

  • RoutingSlipHeaderValueMessageProcessor接受一个已解析的路由表path条目的String数组,并返回(从processMessage())一个带有path作为key0作为初始routingSlipIndexsingletonMap

路由表path条目可以包含MessageChannel bean名称、RoutingSlipRouteStrategy bean名称和Spring表达式(SpEL)。RoutingSlipHeaderValueMessageProcessor在第一次processMessage调用时,会根据BeanFactory检查每个路由表path条目。它将(在应用程序上下文中不是bean名称的)条目转换为ExpressionEvaluatingRoutingSlipRouteStrategy实例。RoutingSlipRouteStrategy条目会被多次调用,直到它们返回null或空String

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

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

对于Java配置,您可以将RoutingSlipHeaderValueMessageProcessor实例添加到HeaderEnricher bean定义中,如以下示例所示

@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")));
}

当端点产生回复且未定义outputChannel时,路由表算法的工作方式如下

  • routingSlipIndex用于从路由表path列表中获取值。

  • 如果routingSlipIndex的值是String,则它用于从BeanFactory获取bean。

  • 如果返回的bean是MessageChannel的实例,则它将用作下一个outputChannel,并且routingSlipIndex在回复消息头中递增(路由表path条目保持不变)。

  • 如果返回的bean是RoutingSlipRouteStrategy的实例,并且其getNextPath不返回空String,则该结果将用作下一个outputChannel的bean名称。routingSlipIndex保持不变。

  • 如果RoutingSlipRouteStrategy.getNextPath返回空Stringnull,则routingSlipIndex递增,并递归调用getOutputChannelFromRoutingSlip以获取下一个路由表path项。

  • 如果下一个路由表path条目不是String,则它必须是RoutingSlipRouteStrategy的实例。

  • routingSlipIndex超过路由表path列表的大小时,算法将转到标准replyChannel头的默认行为。

© . This site is unofficial and not affiliated with VMware.