接上篇RabbitMQ系列04-springboot集成-fanout方式,本篇代码实现direct方式。direct是在fanout的基础上,增加路由过滤,在Direct交换机发布消息时带上路由key,绑定的队列路由key与消息发布的路由key相同时会接收到消息。
生产端
- 配置交换机、队列及绑定关系
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @Description TODO
* @Author chanyu
* @Date 2022/5/27 16:57
* @Version 1.0
**/
@Configuration
public class DirectRabbitConfiguration {
@Bean
public DirectExchange directExchange(){
return new DirectExchange("direct.order.exchange",true,false);
}
@Bean
public Queue smsDirectQueue(){
Queue queue = new Queue("sms.direct.queue",true);
return queue;
}
@Bean
public Queue emailDirectQueue(){
Queue queue = new Queue("email.direct.queue",true);
return queue;
}
@Bean
public Binding smsDirectBinding(){
return BindingBuilder.bind(smsDirectQueue()).to(directExchange()).with("sms");
}
@Bean
public Binding emailDirectBinding(){
return BindingBuilder.bind(emailDirectQueue()).to(directExchange()).with("email");
}
}
- 业务模拟生产消息
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
/**
* @Description TODO
* @Author chanyu
* @Date 2022/5/27 16:52
* @Version 1.0
**/
@Slf4j
@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void orderDirect(String userId , String goodsId , int num , String unit){
// 订单写入
String orderId = UUID.randomUUID().toString();
String msg = "创建订单"+orderId+",用户"+userId+"购买"+num+unit+"商品"+"goodsId";
log.info("创建订单{},用户{}购买{}{}商品{}",orderId,userId,num,unit,goodsId);
// 扣减库存
String exchangeName = "direct.order.exchange";
String routingKey = "sms";
// 发布sms消息
rabbitTemplate.convertAndSend(exchangeName,routingKey,msg);
// // 发布email消息
// rabbitTemplate.convertAndSend(exchangeName,"email",msg);
}
}
消费端
- 消费消息
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/**
* @Description TODO
* @Author chanyu
* @Date 2022/5/27 17:34
* @Version 1.0
**/
@Slf4j
@RabbitListener(queues = {"email.direct.queue"})
@Service
public class DirectEmailService {
@RabbitHandler
public void handlerMsg(String msg){
log.info(msg);
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/**
* @Description TODO
* @Author chanyu
* @Date 2022/5/27 17:34
* @Version 1.0
**/
@Slf4j
@RabbitListener(queues = {"sms.direct.queue"})
@Service
public class DirectSmsService {
@RabbitHandler
public void handlerMsg(String msg){
log.info(msg);
}
}
验证
direct交换机分别绑定了sms /email 两个队列,业务仅发送sms路由key的消息,消费端应该是只有sms队列会接收到消息。
import com.cy.rabbitmqproducer.service.OrderService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit;
@SpringBootTest
class RabbitmqProducerApplicationTests {
@Autowired
private OrderService orderService;
@Test
void order() throws InterruptedException {
orderService.orderDirect("1","1",3,"件");
TimeUnit.SECONDS.sleep(1);
orderService.orderDirect("1","2",1,"个");
TimeUnit.SECONDS.sleep(1);
orderService.orderDirect("1","3",2,"条");
TimeUnit.SECONDS.sleep(1);
orderService.orderDirect("1","4",1,"件");
TimeUnit.SECONDS.sleep(1);
}
}
执行order(),创建了4条订单,发送4条消息(路由key=sms)。
从控制台队列中可以看到消息数,email队列没有消息,sms队列4条消息
查看sms队列的消息,与生产的消息一致。
- 消费
运行消费端工程,只有sms队列消费到消息。
总结
direct模式关键在于路由key,交换机发送消息带上路由key,只有绑定交换机的队列并且路由key能对上的能接收到该消息。