【Spring】使用Spring和AMQP發送接收消息(下)

上篇講了RabbitMQ鏈接工廠的做用是用來建立RabbitMQ的鏈接,本篇就來說講RabbitMQ的發送消息。經過RabbitMQ發送消息最簡單的方式就是將connectionFactory Bean注入到服務層類中,並使用它建立Connection,使用這個Connection來建立Channel,再使用這個Channel發佈消息到Exchange中。java

固然Spring AMQP提供了RabbitTemplate來簡便咱們的操做,消除RabbitMQ發送和接收消息相關的樣板代碼。使用RabbitTemplate也是先在配置文件中寫相關的配置,使用Rabbit命名空間的<template>元素,以下:程序員

<template id="rabbitTemplate" connection-factory="connectionFactory">

如今要發送消息只須要將模板bean注入到服務層類中(這裏以SendServiceImpl爲例),並使用它來發送Spittle,使用RabbitTemplate來發送Spittle提醒,代碼以下:spring

public class SendServiceImpl implements SendService {
    private RabbitTemplate rabbit;

    @Autowired
    public SendServiceImpl (RabbitTemplate rabbit) {
        this.rabbit = rabbit;
    }

    public void sendSpittle (Spittle spittle) {
        rabbit.convertAndSend("spittle.test.exchange", "spittle.test", spittle);
    }
}

上面代碼中sendSpittle()調用RabbitTemplate的convertAndSend()方法,傳入的三個參數分別是Exchange的名稱、routing key以及要發送的對象。
這裏若是使用最簡單的只傳要發送的對象的重載方法,RabbitTemplate就使用默認的Exchange和routing key。按以前配置的話,這兩項默認都爲空,也能夠自行在<template>元素上藉助exchange和routing-key屬性配置不一樣的默認值:數組

<template id="rabbitTemplate" connection-factory="connectionFactory"
    exchange="spittle.test.exchange" 
    routing-key="spittle.test" />

此外RabbitTemplate還有其餘方法能夠用來發送消息,好比用send()方法來發送org.springframework.amqp.core.Message對象,以下所示:異步

Message message = new Message("Hello World".getBytes(), new MessageProperties());
rabbit.send("hello.exchange", "hello.routing", message);

使用send()方法的技巧在於構造要發送的Message對象,在上面的例子中,經過給定字符串的字節數組來構建Message實例。這裏是字符串相對比較簡單,若是消息是複雜對象的話,則會比較複雜。也是由於這樣,因此通常會用convertAndSend()方法,它會自動將對象轉換爲Message,不過它須要一個消息轉換器來幫助完成該任務,默認的轉換器是SimpleMessageConverter,它適用於String、Serializable實例和字節數組。this

發送消息完後,接下來就是接收消息了。
在傳統JMS中有兩種從隊列獲取信息的方式,使用JmsTemplate的同步方式以及使用消息驅動pojo的異步方式。Spring AMQP也提供了相似的方式來獲取經過AMQP發送的消息。線程

使用RabbitTemplate來接收消息code

RabbitTemplate提供的接收信息的方法中最簡單的就是receive()方法,經過該方法就能夠從隊列中獲取一個Message對象:xml

Message message = rabbit.receive("spittle.test.queue");

或者也能夠經過配置獲取消息的默認隊列,這是經過在配置模板的時候,設置queue屬性實現的:對象

<template id="rabbitTemplate" 
    connection-factory="connectionFactory"
    exchange="spittle.test.exchange" 
    routing-key="spittle.test" 
    queue="spittle.test.queue" />

這樣的話,在調用receive()方法時,不須要設置任何參數就能從默認隊列中獲取消息:

Message message = rabbit.receive( );

獲取到Message對象後,通常須要將它的body屬性中的字節數組轉換爲想要的對象,就像在發送的時候將領域對象轉換爲Message同樣,將接收到的Message轉換爲領域對象也很繁瑣。這裏能夠考慮使用RabbitTemplate的receiveAndConvert()方法做爲替代方案:

Spittle spittle = (Spittle) rabbit.receiveAndConvert("spittle.test.queue");

receiveAndConvert()方法會使用與sendAndConvert()方法相同的消息轉換器,將Message對象轉換爲原始的類型。
調用receive()和receiveAndConvert()方法都會當即返回,若是隊列中沒有等待的消息,將會獲得null。這時通常須要程序員本身管理輪詢以及必要的線程,實現隊列監控。若是不想每次都同步輪詢等待消息到達,可使用Spring AMQP提供的消息驅動pojo,下面就看看使用消息驅動pojo的方式來接收消息。

使用消息驅動pojo來接收消息

若是想要在消息驅動pojo中異步地消費使用Spittle對象,先要解決這個pojo自己,以下的SpittleTestHandler扮演了這個角色:

public class SpittleTestHandler {
    public void handleSpittleTest (Spittle spittle) {
        ...
    }
}

其實這個類並無依賴於AMQP,無論經過什麼機制傳遞過來Spittle對象,它都可以處理。
這裏還須要在Spring應用上下文中將SpittleTestHandler聲明爲一個bean:

<bean id="spittleListener"
    class="com.***.spittr.test.SpittleTestHandler">

最後要聲明一個監聽器容器和監聽器,當消息到達的時候,可以調用SpittleTestHandler,配置以下:

<listener-container connection-factory="connectionFactory">
    <listener ref="spittleListener" 
          method="handleSpittleTest"
          queue-names="spittle.test.queue" />
</listener-container>

上面的<listener-container>與<listener>元素都來自rabbit命名空間。並經過queue-names屬性來指定要監聽的隊列,這裏只設定了一個要監聽的隊列,若是要設置多個隊列的話,用逗號隔開。到這裏消息接收就完成了,拿到消息後就能夠在相應方法裏執行相應處理了,使用AMQP發送接收消息就講解到此了。

相關文章
相關標籤/搜索