RabbitMQ 在 Spring Boot 进阶之交换器 Direct Exchange

上篇文章中我们只看到了的生产者的消息发送与消费者的消息消费,实际上它隐藏了rabbitMQ中一个重要的环节。
上篇文章中,我们在生产者中直接定义了消息送达队列的名字

@Component
public class Sender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        String context = "hello " + new Date();
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("hello", context);
    }

}

我们指定了将消息发送到< hello >这个队列中。但是这样在实际使用时,往往难以满足某些业务需求。
所以RabbitMQ给我们提供了四种交换器来满足不同的需求。
分别是:Direct、Fanout、Topic、Headers

假如我们目前有一个业务,它负责资料的上传。

第一个需求是,不同的用户上传后,后续的处理不同。

  • 比如说我们的普通用户上传资料后,可以获得一定的积分。
  • 内部人员上传资料后,不需要积分,但它会增加一定的业绩。

按照上一篇文章的做法,我们是无法用一个队列来完成这部分操作的。

这时候我们可以使用Direct交换器,将业绩队列与积分队列绑定到我们的交换器上。


  • 首先定义一个交换器,名字随便起。
     static final String ExchangeName = "spring-boot-exchange";

    @Bean
    DirectExchange exchange() {
        return new DirectExchange(ExchangeName);
    }
  • 然后定义两个Queue,一个是pointQueue,积分队列。另一个是performanceQueue,业绩队列。
    static final String pointQueueName = "point";

    static final String performanceQueueName = "performance";
    @Bean
    Queue performanceQueue() {
        return new Queue(performanceQueueName, false);
    }

    @Bean
    Queue pointQueue() {
        return new Queue(pointQueueName, false);
    }
  • 将两个Queue绑定到交换器上。这里BindingBuilder的with方法,即routingKey是我们的路由键,交换器将根据这里定义的路由键规则进行队列消息的分发。
    @Bean
    Binding bindingPerformance(Queue performanceQueue, DirectExchange exchange) {
        return BindingBuilder.bind(performanceQueue)
                             .to(exchange)
                             .with(performanceQueueName);
    }

    @Bean
    Binding bindingPointQueue(Queue pointQueue, DirectExchange exchange) {
        return BindingBuilder.bind(pointQueue)
                             .to(exchange)
                             .with(pointQueueName);
    }
  • 定义两个消费者
@Component
public class PointReceiver {

    public void receivePointMessage(String message) {
        System.out.println("接收到来自积分队列的信息 <" + message + ">");
    }

}

@Component
public class PerformanceReceiver {

    public void receivePerformanceMessage(String message) {
        System.out.println("接收到来自业绩队列的信息 <" + message + ">");
    }
}
  • 为消费者配置监听器
    @Bean
    MessageListenerAdapter pointListenerAdapter(PointReceiver receiver) {
        return new MessageListenerAdapter(receiver, "receivePointMessage");
    }

    @Bean
    MessageListenerAdapter performanceListenerAdapter(PerformanceReceiver receiver) {
        return new MessageListenerAdapter(receiver, "receivePerformanceMessage");
    }
  • 将监听器配置到 Container 中
    @Bean
    SimpleMessageListenerContainer pointContainer(ConnectionFactory connectionFactory,
        MessageListenerAdapter pointListenerAdapter) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(pointQueueName);
        container.setMessageListener(pointListenerAdapter);
        return container;
    }

    @Bean
    SimpleMessageListenerContainer performanceContainer(ConnectionFactory connectionFactory,
        MessageListenerAdapter performanceListenerAdapter) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.setQueueNames(performanceQueueName);
        container.setMessageListener(performanceListenerAdapter);
        return container;
    }
  • 测试类如下,在这里,我们使用rabbitTemplate,在ExchangeName这个之前定义的交换器上,配置分发的规则,也就是第二个参数 routingKey 路由键。
@Component
public class Runner implements CommandLineRunner {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Sending message>>>");
        rabbitTemplate.convertAndSend(ExchangeName, pointQueueName, "增加积分~");
        rabbitTemplate.convertAndSend(ExchangeName, performanceQueueName, "增加业绩~");
    }
}
  • 程序运行,控制台输出
Sending message>>>
接收到来自业绩队列的信息 <增加业绩~>
接收到来自积分队列的信息 <增加积分~>

这说明分发时,我们使用的交换器已经成功地通过路由键进行了消息的分发。
并且监听器也根据队列的不同,将消息送达到了不同的消费者中。

这就是rabbitMQ的Direct Exchange。

Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “dog”,则只有被标记为“dog”的消息才被转发,不会转发dog.puppy,也不会转发dog.guard,只会转发dog。

这里写图片描述

参考文章:
http://blog.csdn.net/rainday0310/article/details/22082503
https://spring.io/guides/gs/messaging-rabbitmq/
以及书籍《RabbitMQ实战 高效部署分布式消息队列》

猜你喜欢

转载自blog.csdn.net/anurnomeru/article/details/80093539