此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Integration 6.5.1! |
路由单
从版本 4.1 开始,Spring Integration 提供了路由单企业集成模式的实现。
它被实现为routingSlip
消息头,用于确定AbstractMessageProducingHandler
实例,当outputChannel
未为终结点指定。
此模式在复杂的动态情况下非常有用,因为配置多个路由器来确定消息流可能会变得困难。
当消息到达没有output-channel
这routingSlip
以确定将消息发送到的下一个通道。
当路由滑移耗尽时,正常replyChannel
处理简历。
路由单的配置显示为HeaderEnricher
option — 一个以分号分隔的路由单,其中包含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
接受String
已解析的路由滑移数组path
条目和返回(从processMessage()
) 一个singletonMap
使用path
如key
和0
作为初始routingSlipIndex
.
路由单path
条目可以包含MessageChannel
豆名,RoutingSlipRouteStrategy
bean 名称和 Spring 表达式 (SpEL)。
这RoutingSlipHeaderValueMessageProcessor
检查每个路由单path
条目对BeanFactory
在第一个processMessage
调用。
它将条目(在应用程序上下文中不是 bean 名称)转换为ExpressionEvaluatingRoutingSlipRouteStrategy
实例。RoutingSlipRouteStrategy
条目被多次调用,直到它们返回 null 或空String
.
由于路由单涉及getOutputChannel
process,我们有一个请求-回复上下文。
这RoutingSlipRouteStrategy
已引入以确定下一个outputChannel
使用requestMessage
和reply
对象。
此策略的实现应在应用程序上下文中注册为 bean,并在路由单中使用其 bean 名称path
.
这ExpressionEvaluatingRoutingSlipRouteStrategy
提供了实现。
它接受 SpEL 表达式和内部ExpressionEvaluatingRoutingSlipRouteStrategy.RequestAndReply
对象用作评估上下文的根对象。
这是为了避免EvaluationContext
为每个人创建ExpressionEvaluatingRoutingSlipRouteStrategy.getNextPath()
调用。
它是一个简单的 Java bean,具有两个属性:Message<?> request
和Object reply
.
通过这个表达式实现,我们可以指定路由单path
条目(例如,@routingSlipRoutingPojo.get(request, reply)
和request.headers[myRoutingSlipChannel]
)并避免为RoutingSlipRouteStrategy
.
这requestMessage 参数始终是一个Message<?> .
根据上下文,回复对象可能是Message<?> 一AbstractIntegrationMessageBuilder ,或任意应用程序域对象(例如,当它由服务激活器调用的 POJO 方法返回时)。
在前两种情况下,通常的Message 属性 (payload 和headers ) 在使用 SpEL(或 Java 实现)时可用。
对于任意域对象,这些属性不可用。
因此,如果将结果用于确定下一条路径,则在将路由单与 POJO 方法结合使用时要小心。 |
如果分布式环境中涉及布线单,我们建议不要对布线单使用内联表达式path .
此建议适用于分布式环境,例如跨 JVM 应用程序,使用request-reply 通过消息代理(例如AMQP 支持或 JMS 支持),或使用MessageStore (消息存储)在集成流程中。
该框架使用RoutingSlipHeaderValueMessageProcessor 将它们转换为ExpressionEvaluatingRoutingSlipRouteStrategy 对象,它们用于routingSlip 消息头。
由于这个类不是Serializable (不可能,因为它取决于BeanFactory ),整个Message 变得不可序列化,并且在任何分布式作中,我们最终都会得到一个NotSerializableException .
要克服此限制,请注册一个ExpressionEvaluatingRoutingSlipRouteStrategy bean 具有所需的 SpEL,并在路由单中使用其 bean 名称path 配置。 |
对于 Java 配置,您可以添加一个RoutingSlipHeaderValueMessageProcessor
instance 添加到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 是
MessageChannel
,它用作下一个outputChannel
和routingSlipIndex
在回复邮件头中递增(路由单path
条目保持不变)。 -
如果返回的 bean 是
RoutingSlipRouteStrategy
及其getNextPath
不返回空的String
,则该结果将用作下一个 Bean 名称outputChannel
. 这routingSlipIndex
保持不变。 -
如果
RoutingSlipRouteStrategy.getNextPath
返回一个空的String
或null
这routingSlipIndex
递增,并且getOutputChannelFromRoutingSlip
为下一个布线单递归调用path
项目。 -
如果下一个路由单
path
条目不是String
,它必须是RoutingSlipRouteStrategy
. -
当
routingSlipIndex
超过布线单的大小path
list,则算法将移至标准的默认行为replyChannel
页眉。