一、fanout发布/订阅模式
生产者可以将消息发送给不同类型的消费者。做到发布一次,消费多次。如下图:
- 代码演示
1、生产者模拟下订单
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
//fanout模式模拟下单
public void makeOrderFanout(String userId, String productId, int num) {
//1、生成订单
String orderId = UUID.randomUUID().toString();
System.out.println("fanout生成订单:" + orderId);
//2、通过MQ队列完成消息分发
String exchangeName = "fanout-order-exchange";
String routingKey = "";
rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
}
}
2、三个消费者绑定交换机
@Configuration
public class FanoutRabbitmqConfig {
//1、声明注册fanout式交换机
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange("fanout-order-exchange", true, false);
}
//2、声明三个队列
@Bean
public Queue smsQueue() {
return new Queue("sms-fanout-queue", true);
}
@Bean
public Queue dxQueue() {
return new Queue("dx-fanout-queue", true);
}
@Bean
public Queue emailQueue() {
return new Queue("email-fanout-queue", true);
}
//3、完成交换机和队列的绑定关系
@Bean
public Binding smsBinding() {
return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
}
@Bean
public Binding dxBinding() {
return BindingBuilder.bind(dxQueue()).to(fanoutExchange());
}
@Bean
public Binding emailBinding() {
return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
}
}
3、三个消费者消费消息
@Component
@RabbitListener(queues = "sms-fanout-queue")
public class FanoutSmsService {
@RabbitHandler
public void recieveMesage(String msg) {
System.out.println("fanout的sms队列接收到了消息:" + msg);
}
}
@Component
@RabbitListener(queues = "email-fanout-queue")
public class FanoutEmailService {
@RabbitHandler
public void recieveMesage(String msg) {
System.out.println("fanout邮件队列接收到了消息:" + msg);
}
}
@Component
@RabbitListener(queues = "dx-fanout-queue")
public class FanoutDxService {
@RabbitHandler
public void recieveMesage(String msg) {
System.out.println("fanout短信队列接收到了消息:" + msg);
}
}
4、测试代码
@SpringBootTest
class SpringbootRabbitmqApplicationTests {
@Autowired
private OrderService orderService;
@Test
void contextLoads() {
orderService.makeOrderFanout("1", "1", 12);
}
}
运行结果:
生产者:
消费者:
二、direct路由模式
路由模式跟发布订阅模式类似,路由模式是在订阅模式的基础上加上了路由键key,订阅模式是分发到所有绑定到交换机的队列,路由模式只分发到绑定在交换机上面指定路由键的队列,如下图:
- 代码演示
1、生产者模拟下单
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
//direct模式模拟下单
public void makeOrderDirect(String userId, String productId, int num) {
//1、生成订单
String orderId = UUID.randomUUID().toString();
System.out.println("direct模式生成订单:" + orderId);
//2、通过MQ队列完成消息分发
String exchangeName = "direct-order-exchange";
rabbitTemplate.convertAndSend(exchangeName, "dx", orderId);
rabbitTemplate.convertAndSend(exchangeName, "wx", orderId);
}
}
2、给消费者根据路由键key绑定交换机(只给短信和微信指定路由键)
@Configuration
public class DirectRabbitmqConfig {
//1、声明注册direct式交换机
@Bean
public DirectExchange directExchange() {
return new DirectExchange("direct-order-exchange", true, false);
}
//2、声明三个队列
@Bean
public Queue wxDirectQueue() {
return new Queue("wx-direct-queue", true);
}
@Bean
public Queue dxDirectQueue() {
return new Queue("dx-direct-queue", true);
}
@Bean
public Queue emailDirectQueue() {
return new Queue("email-direct-queue", true);
}
//3、完成交换机和队列的饿绑定关系
@Bean
public Binding wxDirectBinding() {
return BindingBuilder.bind(wxDirectQueue()).to(directExchange()).with("wx");
}
@Bean
public Binding dxDirectBinding() {
return BindingBuilder.bind(dxDirectQueue()).to(directExchange()).with("dx");
}
@Bean
public Binding emailDirectBinding() {
return BindingBuilder.bind(emailDirectQueue()).to(directExchange()).with("email");
}
}
3、消费者消费消息
@Component
public class DirectDXService {
@RabbitListener(queues = "dx-direct-queue")
public void recieveMesage(String msg) {
System.out.println("direct短信队列接消费了消息:" + msg);
}
}
@Component
public class DirectEmailService {
@RabbitListener(queues = "email-direct-queue")
public void recieveMesage(String msg) {
System.out.println("direct邮件队列接消费了消息:" + msg);
}
}
@Component
public class DirectWXService {
@RabbitListener(queues = "sms-direct-queue")
public void recieveMesage(String msg) {
System.out.println("direct的微信队列接收到了消息:" + msg);
}
}
4、测试代码
@SpringBootTest
class RabbitmqProducerApplicationTests {
@Autowired
private OrderService orderService;
@Test
void contextLoadsDirect() {
orderService.makeOrderDirect("1", "1", 12);
}
}
运行结果:
生产者:
消费者:
三、topic主题模式
topics 主题模式跟 routing 路由模式类似,只不过路由模式是指定固定的路由键 routingKey,而主题模式是可以模糊匹配路由键 routingKey,可以类比为mysql中的like模糊查询,如下图
- 代码演示
1、模拟生产者下单
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
//topic模式模拟下单
public void makeOrderTopic(String userId, String productId, int num) {
//1、生成订单
String orderId = UUID.randomUUID().toString();
System.out.println("topic生成订单:" + orderId);
//2、通过MQ队列完成消息分发
String exchangeName = "topic-order-exchange";
String routingKey = "haha.dx.email";
rabbitTemplate.convertAndSend(exchangeName, routingKey, orderId);
}
}
2、消费者队列绑定路由器(设置路由键之匹配短信和邮件)
@Configuration
public class TopicRabbitmqConfig {
//1、声明注册topic式交换机
@Bean
public TopicExchange topicExchange() {
return new TopicExchange("topic-order-exchange", true, false);
}
//2、声明三个队列
@Bean
public Queue wxtopicQueue() {
return new Queue("wx-topic-queue", true);
}
@Bean
public Queue dxtopicQueue() {
return new Queue("dx-topic-queue", true);
}
@Bean
public Queue emailtopicQueue() {
return new Queue("email-topic-queue", true);
}
//3、完成交换机和队列的绑定关系
@Bean
public Binding wxtopicBinding() {
return BindingBuilder.bind(wxtopicQueue()).to(topicExchange()).with("com.#");
}
@Bean
public Binding dxtopicBinding() {
return BindingBuilder.bind(dxtopicQueue()).to(topicExchange()).with("*.dx.*");
}
@Bean
public Binding emailtopicBinding() {
return BindingBuilder.bind(emailtopicQueue()).to(topicExchange()).with("*.#.email");
}
}
3、短信和邮件队列消费生产者消息
@Component
@RabbitListener(queues = "dx-topic-queue")
public class TopicDXService {
@RabbitHandler
public void recieveMesage(String msg) {
System.out.println("topic短信队列接消费了消息:" + msg);
}
}
@Component
@RabbitListener(queues = "email-topic-queue")
public class TopicEmailService {
@RabbitHandler
public void recieveMesage(String msg) {
System.out.println("topic邮件队列接消费了消息:" + msg);
}
}
@Component
@RabbitListener(queues = "wx-topic-queue")
public class TopicWXService {
@RabbitHandler
public void recieveMesage(String msg) {
System.out.println("topic的sms队列接消费了消息:" + msg);
}
}
4、测试代码
@SpringBootTest
class RabbitmqProducerApplicationTests {
@Autowired
private OrderService orderService;
@Test
void contextLoadsTopic() {
orderService.makeOrderTopic("1", "1", 12);
}
}
运行结果:
生产者:
消费者: