一、RabbitMQ"发布/订阅模式"简介
RabbitMQ有七种队列模型,"简单队列"、"工作队列"、"发布订阅"、"路由模式"、"主题模式"、"RPC模式"、"发布者确认模式"。
官网地址:https://www.rabbitmq.com/getstarted.html
发布/订阅模式:
消息的生产者(图中蓝色的P),生产一条消息,将消息发送到交换机(图中紫色的X)中,再由交换机发送到与此交换机绑定的所有队列中,最后由消费者(图中蓝色的C1,C2)消费消息。
*交换机:只负责转发消息,不存储消息,如果交换机没有绑定队列,或者没有符合路由规则的队列,消息就会被交换机抛弃。在7种队列模式中,同样用到交换机的还有"发布订阅"、"主题模式"。不同队列模式的交换机的类型是不一样的,"路由模式"的交换机类型为direct,"发布订阅模式"的交换机类型为fanout,"主题模式"的交换机类型为topic。
*队列:一个队列可以有多个消费者,但发送到队列的消息只能被其中一个消费。
在"发布订阅模式"中,交换机和队列要进行绑定,发送消息时要指定交换机,交换机把消息发送到与之绑定的全部队列中,如果没有绑定的队列,交换机会将消息抛弃。
二、"发布/订阅模式"代码的实现
2.1 引入jar包
<!-- rabbitmq依赖 strat-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- rabbitmq依赖 end-->
2.2 yaml配置文件增加mq配置
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
2.3 RabbitMQ配置文件
创建队列,创建交换机,交换机与队列绑定。
@Configuration
public class RabbitConfig {
/**
* @Description 创建2个队列
**/
@Bean
public Queue fruitsQueue(){
return new Queue("fruits_queue");
}
@Bean
public Queue meatQueue(){
return new Queue("meat_queue");
}
/**
* @Description 声明一个Fanout类型的交换机
**/
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange("xue_exchange");
}
/**
* @Title 将上面的2个队列绑定到Fanout交换机
**/
@Bean
Binding bindExchangeFruits(Queue fruitsQueue, FanoutExchange fanoutExchange){
return BindingBuilder.bind(fruitsQueue).to(fanoutExchange);
}
@Bean
Binding bindExchangeMeat(Queue meatQueue,FanoutExchange fanoutExchange){
return BindingBuilder.bind(meatQueue).to(fanoutExchange);
}
}
2.4 生产者
@Component
public class Publisher {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 生产者将消息发送到Fanout交换机
**/
public void sendMessage() {
String message = "food";
System.out.println("发送消息 : " + message);
rabbitTemplate.convertAndSend("xue_exchange","",message);
}
}
2.5 消费者
@Component
public class Consumer {
@RabbitListener(queues = "fruits_queue")
@RabbitHandler
public void processFruits(String message) {
System.out.println("processFruits消费了队列fruits_queue的消息 " + message);
}
@RabbitListener(queues = "meat_queue")
@RabbitHandler
public void processMeatOne(String message) {
System.out.println("processMeatOne消费了队列meat_queue的消息: " + message);
}
@RabbitListener(queues = "meat_queue")
@RabbitHandler
public void processMeatTwo(String message) {
System.out.println("processMeatTwo消费了队列meat_queue的消息:" + message);
}
}
2.6 测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class FirstprojectApplicationTests {
@Autowired
Publisher publisher;
@Test
public void contextLoads() {
publisher.sendMessage();
}
}