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”演示。這個示例展示了主要元件:訊息通道(Message Channel)和訊息端點(Message Endpoint)。該演示還揭示了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——它實現了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建議的建立。

簡單路由

路由示例包含一個訊息端點,該端點每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";
    }
}

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


@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 社群所有即將舉行的活動。

檢視所有