Spring Integration 範例

工程 | Mark Fisher | 2007 年 12 月 21 日 | ...

在我最近的文章中,我提到 Spring Integration 的 Subversion 儲存庫很快就會公開存取,我很樂意現在提供該連結。 您可以使用以下指令檢查專案

svn co https://anonsvn.springframework.org/svn/spring-integration/base/trunk spring-integration

如果檢查成功,您應該會看到以下目錄結構

spring-integration/
  +--build-spring-integration/
  +--spring-build/
  +--spring-integration-core/
  +--spring-integration-samples/

我想藉此機會介紹 'spring-integration-samples' 中的幾個範例。 請記住,這個專案絕對還在開發中(目前為 0.5 SNAPSHOT),但這些範例應該可以讓您了解程式設計模型的成形方式,而且我非常期待收到一些回饋。

Hello World

第一個範例是強制性的 "Hello World" 示範。 這個範例展示了主要元件:訊息通道和訊息端點。 這個示範也揭示了 Spring Integration 方法是非侵入性的 - 在業務邏輯和訊息傳遞之間提供完全的關注點分離。 在這種情況下,"業務邏輯" 是一個簡單的 HelloService

public class HelloService {

    public String sayHello(String name) {
        return "Hello " + name;
    }
}

這個範例使用基於 XML 的設定來設定訊息端點(我們接下來將看到註解方法)


<endpoint input-channel="inputChannel"
               default-output-channel="outputChannel"
               handler-ref="helloService"
               handler-method="sayHello"/>

您會看到 'handler-ref' 只是指向一個由 Spring 管理的 bean。 如果您使用 Spring 的 MessageListenerAdapter 進行非同步 JMS 接收,那麼這應該看起來很熟悉 - 特別是如果您使用 Spring 2.5 的新 jms 命名空間和 "jms:listener" 元素。 最後,HelloWorldDemo 啟動應用程式內容,然後與通道互動


ChannelRegistry channelRegistry = (ChannelRegistry) context.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
MessageChannel inputChannel = channelRegistry.lookupChannel("inputChannel");
MessageChannel outputChannel = channelRegistry.lookupChannel("outputChannel");
inputChannel.send(new StringMessage(1, "World"));
System.out.println(outputChannel.receive().getPayload());

這個範例涉及查找 MessageBus bean - 該 bean 實現了 ChannelRegistry 介面。 但是,在非示範的 "真實世界" 場景中,任何會存取通道的元件都可以透過依賴注入來提供登錄檔。 它只需要實作 ChannelRegistryAware (或使用 @Autowired)。 這與 Spring 中其他地方使用的方法相同 - 例如 ApplicationEventPublisherAware

註解驅動的端點和訂閱者

下一個範例示範如何使用註解設定訊息端點。 事實上,這個特定的端點甚至提供了資料,這些資料(在幕後)會使用 @Polled 方法註解轉換為訊息有效負載內容。 或者,它可以提供一個輸入通道來非同步接收訊息。

@MessageEndpoint(defaultOutput="quotes")
public class QuotePublisher {

    @Polled(period=300)
    public Quote getQuote() {
        BigDecimal price = new BigDecimal(new Random().nextDouble() * 100);
        return new Quote(generateTicker(), price.setScale(2, RoundingMode.HALF_EVEN));
    }

    private String generateTicker() {
        // randomly generates 3-letter tickers
    }
}

在接收端,有一個 @Subscriber 註解


public class QuoteSubscriber {

    @Subscriber(channel="quotes")
    public void log(Object o) {
        System.out.println(o);
    }
}

這是註冊註解後處理器和 2 個由 Spring 管理的 bean 的 XML(請注意,這個範例使用 'spring-integration' 模式作為主要命名空間。


<beans:beans xmlns="http://www.springframework.org/schema/integration"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/integration
                http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">

    <message-bus/>

    <annotation-driven/>

    <channel id="quotes"/>

    <beans:bean id="publisher" class="org.springframework.integration.samples.quote.QuotePublisher"/>

    <beans:bean id="subscriber" class="org.springframework.integration.samples.quote.QuoteSubscriber"/>

</beans:beans>

順帶一提,'annotation-driven' 元素也啟用了 @Publisher 註解,該註解會觸發 AOP advice 的建立,以非同步方式將任何帶註解方法的回傳值傳送到通道。

簡單路由

路由範例的特色是一個訊息端點,該端點每 3 秒產生一個遞增的整數,以及一個解析目標通道名稱的路由器(請注意,路由器方法也可以傳回多個結果,並且可以傳回實際的 MessageChannel 實例,而不是名稱)。

@MessageEndpoint
public class Counter {

    private AtomicInteger count = new AtomicInteger();

    @Polled(period=3000)
    public int getNumber() {
        return count.incrementAndGet();
    }

    @Router
    public String resolveChannel(int i) {
        if (i % 2 == 0) {
            return "even";
        }
        return "odd";
    }
}

在這些通道的接收端,我們有 2 種不同的方法,它們只是記錄訊息有效負載


@Component
public class NumberLogger {

    @Subscriber(channel="even")
    public void even(int i) {
        System.out.println("even: " + i);
    }

    @Subscriber(channel="odd")
    public void odd(int i) {
        System.out.println("odd:  " + i);
    }
}

順帶一提,請注意 NumberLogger 使用 Spring 的 @Component 進行註解。 @MessageEndpoint 註解也包含 @Component 作為元註解。 因此,兩者都是 "刻板印象",並且可以使用 Spring 2.5 的類路徑掃描進行自動偵測。 這個範例的 XML 非常簡單


<context:component-scan base-package="org.springframework.integration.samples.oddeven"/>

<message-bus auto-create-channels="true"/>

<annotation-driven/>

希望這能為 Spring Integration 程式設計模型提供一個不錯的介紹。 歡迎隨時檢查程式碼並親自試用這些範例。 我目前正在編寫一份 "入門" 指南,我將在假期後提供該指南。 如果您確實檢查了程式碼,請務必頻繁更新。 程式碼不斷發展,特別是我正在重構許多核心消費者/派送器程式碼,目的是為新增輪詢或事件驅動的訊息來源提供最簡單的擴充點。 在下一篇部落格文章中,我計劃展示 'spring-integration-samples' 的一些新新增功能,這些功能以這些擴充點為特色。

取得 Spring 電子報

隨時關注 Spring 電子報

訂閱

領先一步

VMware 提供培訓和認證,以加速您的進度。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔。

了解更多

即將舉行的活動

查看 Spring 社群中所有即將舉行的活動。

查看全部