前面得八篇文章相信小伙伴对RabbitMQ基础API有了一定得了解,今天我们来讲解如何使用Spring Boot来进行RabbitMQ得开发,不过如果小伙伴对RabbitMQ基础API还不了解得建议大家翻阅博主的前面8篇文章;我们就先从Spring AMQP开始介绍;
Spring AMQP项目将核心Spring概念应用基于AMQP的消息传递解决方案的开发。 Spring提供“模板”作为发送和接收消息的高级抽象。 Spring还为消息驱动的POJO提供支持。 这些库有助于管理AMQP资源,同时促进依赖注入和声明性配置的使用;简单说就是Spring AMQP帮我们对RabbitMQ进行了进一步得封装,并交给Spring管理和以前的Spring bean 一样让我们使用起来更加得方便;
让我们先来看一下一下官方文档中使用简单的命令式Java来发送和接收消息的代码:(注意我的注释)
//创建连接工厂
ConnectionFactory connectionFactory = new CachingConnectionFactory();
//AmqpAdmin是作用于操作RabbitMQ的类,可以创建队列 、 交换机 等等
AmqpAdmin admin = new RabbitAdmin(connectionFactory);
//创建队列
admin.declareQueue(new Queue("myqueue"));
//AmqpTemplate消息发送模板
AmqpTemplate template = new RabbitTemplate(connectionFactory);
//convertAndSend发送消息
template.convertAndSend("myqueue", "foo");
//receiveAndConvert 接收消息
String foo = (String) template.receiveAndConvert("myqueue");
通过以代码我们会发现,和我们基础RabbitMQ的构建方式还是很像的,同样拥有ConnectionFactory ,需要构建队列构建交换机(代码中没构建,使用的是RabbitMQ默认交换机),通过AmqpTemplate 发送、接收消息;那么交给Spring管理后我们需要如何来进行配置?从而实现上述代码的效果?
收发代码:
ApplicationContext context = new GenericXmlApplicationContext("classpath:/rabbit-context.xml");
AmqpTemplate template = context.getBean(AmqpTemplate.class);
template.convertAndSend("myqueue", "foo");
String foo = (String) template.receiveAndConvert("myqueue")
//注解配置
@Configuration
public class RabbitConfiguration {
@Bean
public ConnectionFactory connectionFactory() {
return new CachingConnectionFactory("localhost");
}
@Bean
public AmqpAdmin amqpAdmin() {
return new RabbitAdmin(connectionFactory());
}
@Bean
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(connectionFactory());
}
@Bean
public Queue myQueue() {
return new Queue("myqueue");
}
}
收发代码:
ApplicationContext context = new AnnotationConfigApplicationContext(RabbitConfiguration.class);
AmqpTemplate template = context.getBean(AmqpTemplate.class);
template.convertAndSend("myqueue", "foo");
String foo = (String) template.receiveAndConvert("myqueue");
与我们之前学习RabbitMQ一样,在使用Spring AMQP之前,我们有必要先去了解一下各个组件的一些介绍,便于我们快速理解与使用;更多详细的讲解请可以参考官方最新文档: Spring AMQP官方文档 这里就不过多介绍了,主要还是以实例来让大家来了解
首先我们使用IDEA构建一个SpringBoot项目,SpringBoot版本选择2.1.3
在POM.XML文件中引入
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-amqp
在springboot配置文件 application.yml 中加入
spring:
rabbitmq:
addresses: 192.168.1.28:5672
username: toher
password: toher888
connection-timeout: 15000
virtual-host: /
publisher-confirms: true #开启消息确认
publisher-returns: true #开去消息Return
template:
mandatory: true #交换机找不到QUEUE时,会调用Basic.Return 命令将消息返回给生产者
listener:
direct:
acknowledge-mode: manual # 开启手动 ,否则confirm自动确认
server:
port: 8089
构建消息发布者,消息确认机制
@Component
public class RabbitSender implements RabbitTemplate.ReturnCallback {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMsg() throws Exception {
CorrelationData cd = new CorrelationData("123456789");
rabbitTemplate.setReturnCallback(this);
rabbitTemplate.convertAndSend("topicExchange001", "topicKey.send","测试发送",cd);
//官方最新文档
//从版本2.1开始,该CorrelationData对象具有ListenableFuture您可以用来获取结果的对象,
//而不是ConfirmCallback在模板上使用
boolean isAck = cd.getFuture().get(10, TimeUnit.SECONDS).isAck();
//如果ACK true 进行业务处理
if(isAck){
//获取发送消息时候的 CorrelationData
System.err.println("ID:" + cd.getId());
}else{
}
}
final RabbitTemplate.ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int replyCode, String replyText,
String exchange, String routingKey) {
System.err.println("--------------进入Return-------------");
System.err.println("return exchange: " + exchange + ", routingKey: "
+ routingKey + ", replyCode: " + replyCode + ", replyText: " + replyText);
}
};
@Override
public void returnedMessage(Message message, int replyCode, String replyText,
String exchange, String routingKey) {
System.err.println("--------------进入Return-------------");
System.err.println("return exchange: " + exchange + ", routingKey: "
+ routingKey + ", replyCode: " + replyCode + ", replyText: " + replyText);
}
//也可以实现 RabbitTemplate.ConfirmCallback 即可
// @Override
// public void confirm(CorrelationData correlationData, boolean ack, String cause) {
// System.err.println("--------------进入Confirm-------------");
// System.err.println("correlationData: " + correlationData);
// System.err.println("ack: " + ack);
// if(!ack){
// System.err.println("异常处理....");
// }
// }
}
构建消息消费者
@Component
public class RabbitReceiver {
/**@Exchange 默认durable=true 故不需要设置 **
*
* @param message
* @param channel
* @throws Exception
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "topicQueue001",
durable="true"),
exchange = @Exchange(value = "topicExchange001"
type= "topic",
ignoreDeclarationExceptions = "true"),
key = "topicKey.*")
)
@RabbitHandler
public void onMessage(Message message, Channel channel) throws Exception {
System.err.println("消费端Payload: " + message.getPayload());
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
//手工ACK
channel.basicAck(deliveryTag, false);
}
}
最后编写一个测试方法进行信息发布
@Test
public void send() throws Exception {
rabbitSender.sendMsg();
}
最终文件目录如下:
运行SpringBoot项目,我们先不着急进行测试,我们先进入RabbitMQ控制台,观察消费者 @RabbitListener 是否帮我们创建了对应的交换机、队列且进行了路由绑定
观察队列
点击队列查看绑定的 路由规则没问题后,我们运行测试方法,出现如下信息证明消息确认成功!
我们测试ReturnCallback仅需要修改,消息发布者的路由KEY,设置一个不存在的
//修改topicKey1.send 让其路由不到队列
rabbitTemplate.convertAndSend("topicExchange001", "topicKey1.send","测试发送",cd);
本问主要介绍了Spring Boot 2.1.3版本的集成Spring AMQP,还是建议大家认真查阅官方的文档,了解各个组件的作用和使用方法,如果在集成过程中有任何问题,欢迎留言~谢谢大家!
上一篇:消息的TTL和RabbitMQ的各种队列介绍
下一篇:Spring Boot使用Spring AMQP的消息分发和限流