【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发送接收消息就讲解到此了。

相关文章
相关标签/搜索