关于RabbitMQ我就不过多介绍了,我得博客前面也有过说明,本篇博客主要介绍一下SpringBoot与RabbitMQ的整合
SpringBoot整合RabbitMQ,RabbitAutoConfiguration
为我们SpringBoot整合RabbitMQ 的自动配置类
- 自动配置了连接工厂 ConnectionFactory
- RabbitProperties封装了 RabbitMQ
- RabbitTemplate:给RabbitMQ发送和接受消息的
- AmqpAdmin:RabbitMQ的系统管理功能组件
我们的项目结构如下
配置文件
我们首先编写配置文件连接RabbitMQ
spring.rabbitmq.host=localhost
spring.rabbitmq.password=guest
spring.rabbitmq.username=guest
spring.rabbitmq.port=5672
这样我们的项目基本配置就OK了
RabbitAutoConfiguration会为我们自动在容器中装配RabbitTemplate
我们使用RabbitTemplate做一个消息生产与消费的Demo
@Test
public void send() {
Map<String,String> map = new HashMap<>();
map.put("firstName","yang");
map.put("lastName","zhao");
rabbitTemplate.convertAndSend("amq.direct","yz.zwl",map);
}
可以看到我们的消息已经存在队列中了,接下来我们进行消费
@Test
public void receive() {
System.out.println(rabbitTemplate.receiveAndConvert("yz.zwl"));
}
可以看到我们已经成功消费了队列中的消息
使用Json方式传递,并传入对象Book
可以看到,我们的队列中的消息并不是以JSON格式存储的,所以我们需要进行配置自定义的消息转化器
@Configuration
public class RabbitConfig {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
接下来我们测试将对象作为消息进行生产消费
@Test
public void send() {
rabbitTemplate.convertAndSend("amq.direct","yz.zwl",new Student("yz","男"));
}
可以看到我们的消息已经以JSON的格式存在队列中
消费消息也完全OK
开启基于注解的方式
RabbitAutoConfiguration同样会为我们自动在容器中装配AmqpAdmin(创建和删除 Exchange 、Queue、Bind,)
我们之前的Demo是我们在RabbitMQManagement系统中自己创建的Exchange、Queue、Bind。接下来我们使用代码的方式进行创建
首先我们创建三种Exchange以及Queue
amqpAdmin.declareExchange(new DirectExchange("yzExchange.direct"));
amqpAdmin.declareExchange(new FanoutExchange("yzExchange.fanout"));
amqpAdmin.declareExchange(new TopicExchange("yzExchange.topic"));
amqpAdmin.declareQueue(new Queue("yz.zwl",true));
amqpAdmin.declareQueue(new Queue("zwl.yz",true));
amqpAdmin.declareQueue(new Queue("yz.news",true));
amqpAdmin.declareQueue(new Queue("yz.china",true));
amqpAdmin.declareQueue(new Queue("zwl.news",true));
我们可以使用RabbitListener注解消费消息,参数为对应的队列 进行监听相关队列
@Service
public class RabbitService {
@RabbitListener(queues = "yz.zwl")
public void receiveDirect(Student student){
System.out.println("yz.zwl消费消息");
System.out.println(student);
}
@RabbitListener(queues = "zwl.yz")
public void receiveDirect1(Student student){
System.out.println("zwl.yz消费消息");
System.out.println(student);
}
@RabbitListener(queues = "yz.news")
public void receiveDirect2(Student student){
System.out.println("yz.news消费消息");
System.out.println(student);
}
}
Direct Exchange
使用AmqpAdmin创建Bind
amqpAdmin.declareBinding(new Binding("yz.zwl",Binding.DestinationType.QUEUE,"yzExchange.direct","yz.zwl",null));
amqpAdmin.declareBinding(new Binding("zwl.yz",Binding.DestinationType.QUEUE,"yzExchange.direct","zwl.yz",null));
amqpAdmin.declareBinding(new Binding("yz.news",Binding.DestinationType.QUEUE,"yzExchange.direct","yz.news",null));
我们将Direct模式的**yzExchange.direct **绑定到yz.zwl、zwl.yz、yz.news
三个队列,并为他们三个声明同名字的routing key
生产消息
rabbitTemplate.convertAndSend("yzExchange.direct","yz.zwl",new Student("yangzhao111","男"));
rabbitTemplate.convertAndSend("zwl.yz",new Student("yangzhao","男"));
可以看到只有对应的队列消费了消息,证实了Direct 点对点的模式
Fanout Exchange
使用AmqpAdmin创建Bind
//fanout
amqpAdmin.declareBinding(new Binding("yz.zwl",Binding.DestinationType.QUEUE,"yzExchange.fanout","yz.zwl",null));
amqpAdmin.declareBinding(new Binding("zwl.yz",Binding.DestinationType.QUEUE,"yzExchange.fanout","zwl.yz",null));
amqpAdmin.declareBinding(new Binding("yz.news",Binding.DestinationType.QUEUE,"yzExchange.fanout","yz.news",null));
我们将Fanout模式的yzExchange.fanout绑定到yz.zwl、zwl.yz、yz.news
三个队列,并为他们三个声明同名字的routing key
生产消息
rabbitTemplate.convertAndSend("yzExchange.fanout","yz.zwl",new Student("yangzhao","男"));
可以看到三个队列都消费了消息,证实了Fanout的广播效果,且与routing key无关
Topic Exchange
使用AmqpAdmin创建Bind
amqpAdmin.declareBinding(new Binding("zwl.yz",Binding.DestinationType.QUEUE,"yzExchange.topic","zwl.*",null));
amqpAdmin.declareBinding(new Binding("yz.zwl",Binding.DestinationType.QUEUE,"yzExchange.topic","*.zwl",null));
amqpAdmin.declareBinding(new Binding("yz.news",Binding.DestinationType.QUEUE,"yzExchange.topic","#.news",null));
我们将Topic模式的yzExchange.topic绑定到yz.zwl、zwl.yz、yz.news
三个队列,并为他们三个声明对应的routing key *.zwl、zwl.*、#.news
生产消息
//topic
rabbitTemplate.convertAndSend("yzExchange.topic","yz.zwl",new Student("yangzhao","男"));
rabbitTemplate.convertAndSend("yzExchange.topic","zwl.news",new Student("yangzhao","男"));
因为我们消息的routing key 与三个Binding的都匹配,所以三个队列都消费了消息
Amqp删除Exchange、Queue
amqpAdmin.deleteExchange("yzExchange.direct");
amqpAdmin.deleteExchange("yzExchange.fanout");
amqpAdmin.deleteExchange("yzExchange.topic");
amqpAdmin.deleteQueue("yz.zwl");
amqpAdmin.deleteQueue("zwl.yz");
amqpAdmin.deleteQueue("yz.news");
amqpAdmin.deleteQueue("yz.china");
amqpAdmin.deleteQueue("zwl.news");