配置通用路由器

Spring Integration 提供了一種通用路由器。你可以使用它進行通用路由(與 Spring Integration 提供的其他具有某種特定功能的路由器不同)。

以下部分解釋了使用 XML 元件配置路由器的方法。

router 元素提供了一種將路由器連線到輸入通道的方式,並且接受可選的 default-output-channel 屬性。 ref 屬性引用自定義路由器實現(必須擴充套件 AbstractMessageRouter)的 bean 名稱。以下示例展示了三個通用路由器

<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 例項(或原型範圍的 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();
}