添加RabbitMQ到Spring中
1.添加RabbitMQ依赖
在使用Spring发送和接收RabbitMQ消息之前,我们需要将Spring Boot的AMQPstarter依赖添加到构建文件中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.配置RabbitMQ属性
添加AMQP starter到构建文件中之后,将会触发自动配置功能,这样会为我们创建一个AMQP连接工厂和RabbitTemplate bean,以及其他的一些支撑组件。我们要使用Spring发送和接收RabbitMQ代理的消息,只需要添加这项依赖就可以了。但是,这里还有一些我们需要掌握的有用属性,如表8.4所示。
对于开发来说,我们可能会使用不需要认证的RabbitMQ代理,它运行在本地机器上并监听5672端口。在开发阶段,这些属性可能没有太大的用处,但是当应用程序投入生产环境时,它们无疑是非常有用的。
假设我们要将应用投入生产环境,RabbitMQ代理位于名为rabbit.tacocloud.com服务器上,监听5673端口并且需要认证。在这种情况下,当prod profile处于激活状态时,application.yml文件中的如下配置将会设置这些属性:
sping
profiles:prod
rabbitmq:
host:rabbit.tacocloud.com
port:5673
username:tacoweb
password:*****
3.通过RabbitTemplate发送消息
Spring对RabbitMQ消息支持的核心是RabbitTemplate。RabbitTemplate与JmsTemplate类似,提供了一组相似的方法。但是,我们将会看到,这里有一些细微的差异,这是与RabbitMQ独特的运行方式有关的。
在使用RabbitTemplate发送消息方面,我们可以使用与JmsTemplate中同名的send()和convertAndSend()方法。但是,与JmsTemplate的方法只是将消息路由至队列或主题不同,RabbitTemplate会按照Exchanges和routing key来发送消息。下面列出关于使用RabbitTemplate发送消息比较重要的一些方法
我们可以看到,前3个send()方法都是发送原始的Message对象。接下来的3个convertAndSend()方法会接受一个对象,这个对象会在发送之前在幕后转换成Message。最后的3个convertAndSend()方法与前面的3个方法类似,但是它们还会接受一个MessagePostProcessor对象,这个对象能够在Message发送至代理之前对其进行操作。
这些方法与JmsTemplate对应方法的不同之处在于,它们会接受String类型的值以指定Exchange和routing key,而不像JmsTemplate那样接受目的地名称(或Destination)。没有接受Exchange参数的方法会将消息发送至DefaultExchange。与之类似,没有指定routing key的方法会把消息路由至默认的routing key。
4.《Spring实战》中的一个小例子
在《Spring实战》这本书中,我们要设计一个在线的墨西哥卷商城。接到用户订单后要通过消息队列来把任务发给厨房。
package tacos.messaging;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tacos.Order;
@Service
public class RabbitOrderMessagingService
implements OrderMessagingService {
private RabbitTemplate rabbit;
@Autowired
public RabbitOrderMessagingService(RabbitTemplate rabbit) {
this.rabbit = rabbit;
}
public void sendOrder(Order order) {
rabbit.convertAndSend("tacocloud.order.queue", order,
new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message)throws AmqpException {
// 通过MessageProperties来提供消息属性
MessageConverter converter = rabbit.getMessageConverter();
MessageProperties props1 = new MessageProperties();
Message message1 = converter.toMessage(order,props1);
rabbit.send("tacocloud.order",message);
}
});
}
}
有了MessageConverter之后,将Order转换成Message就是非常简单的任务了。我们必须通过MessageProperties来提供消息属性,但是如果我们不需要设置任何这样的属性,使用默认的MessageProperties实例就可以了。随后,剩下的就是调用send()了,并将Exchange和routing key(这两者都是可选的)连同消息一起传递过去。在本例中,我们只指定了routing key(tacocloud.order)和消息本身,所以会使用默认的Exchange。
这里提到了默认的Exchange,它的名字是“”(空的String),对应RabbitMQ代理自动生成的Default Exchange。与之相似,默认的routing key也是“”(它的路由将会取决于Exchange以及相应的binding)。我们可以通过设置spring.rabbitmq.template.exchange和spring.rabbitmq.template.routing-key属性重写这些默认值:
spring:
rabbitmq:
template:
exchange:tacocloud.orders
routing-key:kitchens.central
在本例中,所有未指明Exchange的消息都将会自动发送至名为tacocloud.orders的Exchange。如果在调用send()或convertAndSend()的时候也没有指定routingkey,那么消息将会使用值为kitchens.central的routing key。