配置通用路由器
Spring Integration 提供了一个通用路由器。你可以将它用于通用路由(与 Spring Integration 提供的其他具有某种专业化的路由器不同)。
以下部分解释了使用 XML 组件的路由器配置。
router 元素提供了一种将路由器连接到输入通道的方式,并且还接受可选的 default-output-channel 属性。ref 属性引用自定义路由器实现的 bean 名称(它必须扩展 AbstractMessageRouter)。以下示例显示了三个通用路由器
<int:router ref="payloadTypeRouter" input-channel="input1"
default-output-channel="defaultOutput1"/>
<int:router ref="recipientListRouter" input-channel="input2"
default-output-channel="defaultOutput2"/>
<int:router ref="customRouter" input-channel="input3"
default-output-channel="defaultOutput3"/>
<beans:bean id="customRouterBean" class="org.foo.MyCustomRouter"/>
或者,ref 可以指向包含 @Router 注解的 POJO(稍后显示),或者你可以将 ref 与显式方法名结合使用。指定方法会应用本文档稍后在 @Router 注解部分描述的相同行为。以下示例定义了一个路由器,其 ref 属性指向一个 POJO
<int:router input-channel="input" ref="somePojo" method="someMethod"/>
如果自定义路由器实现在其他 <router> 定义中被引用,我们通常建议使用 ref 属性。但是,如果自定义路由器实现应该限制在单个 <router> 定义中,你可以提供一个内部 bean 定义,如以下示例所示
<int:router method="someMethod" input-channel="input3"
default-output-channel="defaultOutput3">
<beans:bean class="org.foo.MyCustomRouter"/>
</int:router>
在同一个 <router> 配置中同时使用 ref 属性和内部处理器定义是不允许的。这样做会产生歧义条件并抛出异常。 |
如果 ref 属性引用了一个扩展 AbstractMessageProducingHandler 的 bean(例如框架本身提供的路由器),则配置会进行优化以直接引用路由器。在这种情况下,每个 ref 属性必须引用一个单独的 bean 实例(或一个 prototype 作用域的 bean),或者使用内部 <bean/> 配置类型。但是,此优化仅在你未在路由器 XML 定义中提供任何特定于路由器的属性时适用。如果你不小心从多个 bean 引用了相同的消息处理器,则会收到配置异常。 |
以下示例显示了在 Java 中配置的等效路由器
@Bean
@Router(inputChannel = "routingChannel")
public AbstractMessageRouter myCustomRouter() {
return new AbstractMessageRouter() {
@Override
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
return // determine channel(s) for message
}
};
}
以下示例显示了使用 Java DSL 配置的等效路由器
@Bean
public IntegrationFlow routerFlow() {
return IntegrationFlow.from("routingChannel")
.route(myCustomRouter())
.get();
}
public AbstractMessageRouter myCustomRouter() {
return new AbstractMessageRouter() {
@Override
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
return // determine channel(s) for message
}
};
}
或者,你可以根据消息负载中的数据进行路由,如以下示例所示
@Bean
public IntegrationFlow routerFlow() {
return IntegrationFlow.from("routingChannel")
.route(String.class, p -> p.contains("foo") ? "fooChannel" : "barChannel")
.get();
}