設定通用路由器

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();
}