「RabbitMQ」使用Direct交换机实现消息的路由与投递

文章介绍了RabbitMQ中的DirectExchange如何通过Bean和注解进行配置,包括创建队列、交换机和绑定关系。此外,展示了消费者如何使用注解监听消息,以及生产者如何发送不同路由键的消息到对应队列。内容涵盖精确匹配路由机制、Spring集成及消息处理。
摘要由CSDN通过智能技术生成

目录

介绍

使用 「Bean」配置 Direct 交换机

使用 「注解 」配置 Direct 交换机①

使用 「注解 」配置 Direct 交换机② 

 模拟生产者发送消息①

 模拟生产者发送消息②


官方网站:RabbitMQ

介绍

        具体来说,Direct Exchange 是一种按照精确匹配方式进行路由的 Exchange,即只有 Routing Key 与 Binding Key 完全匹配的消息才会被路由到指定的 Queue 中。这种精确匹配方式使得应用程序可以非常精细地控制每条消息的处理流程,同时也能够很好地控制消息的负载均衡和可靠性。

使用 「Bean」配置 Direct 交换机

/**
 * 直接交换机Bean配置
 *
 * @author xiangtianlei
 * @date 2023/06/07
 */
@Configuration
public class DirectExchangeConfig {
    @Bean(name = "directQueueOne")
    public Queue directQueueOne() {
        return new Queue("direct_queue_one", true, false, false);
    }

    @Bean(name = "directQueueTwo")
    public Queue directQueueTwo() {
        return new Queue("direct_queue_two", true, false, false);
    }

    @Bean(name = "directExchange")
    public Exchange directExchange() {
        return new DirectExchange("direct_exchange");
    }

    @Bean(name = "directBindingOne")
    public Binding directBindingOne(@Qualifier("directQueueOne") Queue queue, Exchange directExchange) {
        return BindingBuilder.bind(queue).to(directExchange).with("one").noargs();
    }

    @Bean(name = "directBindingTwo")
    public Binding directBindingTwo(@Qualifier("directQueueTwo") Queue queue, Exchange directExchange) {
        return BindingBuilder.bind(queue).to(directExchange).with("two").noargs();
    }

}

@Bean(name = "directQueueOne") 是一种声明 Bean 的注解配置,它会在 Spring 容器中创建一个名为 "directQueueOne" 的 Bean 实例,并返回这个 Bean 实例的引用。通过这个注解,我们就可以将队列定义为一个 Spring Bean,并在需要的地方进行注入,使得它可以被其他组件所使用。

@Qualifier 注解是 Spring 框架中用于指定依赖注入的具体实现类对象的注解。在使用 Spring IoC 容器进行依赖注入时,如果存在多个同类型的实例对象,就需要通过 @Qualifier 注解来标识要注入的实例对象。

例如,假设我们有一个接口 PersonService,它有两个实现类:StudentServiceImplTeacherServiceImpl。如果我们在代码中需要注入 PersonService 类型的对象,但不指定具体的实现类,Spring IoC 容器就会因为无法选择要注入哪个实现类而报错。

使用 「注解 」配置 Direct 交换机①

/**
 * Direct交换机消费者配置
 *
 * @author xiangtianlei
 * @date 2023/06/07
 */
@Component
public class ConsumerDirect {

    Logger logger = LoggerFactory.getLogger(ConsumerDirect.class);


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("direct_queue_one"),
            exchange = @Exchange(name = "direct_exchange", type = ExchangeTypes.DIRECT),
            key = {"one", "two"}
    ))
    public void readDirectQueueOne(String msg) {
        logger.info("当前时间为:{},仅接收key为one和two的队列的消息,接收到的信息为:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), msg);
    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue("direct_queue_two"),
            exchange = @Exchange(name = "direct_exchange", type = ExchangeTypes.DIRECT),
            key = {"two"}
    ))
    public void readDirectQueueTwo(String msg) {
        logger.info("当前时间为:{},仅接收key为two的队列的消息,接收到的信息为:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), msg);
    }

}

使用 「注解 」配置 Direct 交换机② 

/**
 * Direct交换机消费者配置
 *
 * @author xiangtianlei
 * @date 2023/06/07
 */
@Component
@RabbitListener(bindings = @QueueBinding(
        value = @Queue("direct_queue_one"),
        exchange = @Exchange(name = "direct_exchange", type = ExchangeTypes.DIRECT),
        key = {"one", "two", "three"}
))
public class ConsumerDirect {

    Logger logger = LoggerFactory.getLogger(ConsumerDirect.class);


    @RabbitHandler
    public void processMessage(String message) {
        logger.info("当前时间为:{},仅接收key为one和two的队列的消息,入参类型为字符串格式,接收到的信息为:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), message);
    }

    @RabbitHandler
    public void processMessage(@Payload User user) {
        logger.info("当前时间为:{},仅接收key为one和two的队列的消息,入参类型为User对象,接收到的信息为:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), user);
    }

    @RabbitHandler
    public void processMessage(byte[] bytes) {
        logger.info("当前时间为:{},仅接收key为one和two的队列的消息,入参类型为byte,接收到的信息为:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), new String(bytes));
    }

    @RabbitHandler
    public void processMessage(Map<String, Object> map) {
        logger.info("当前时间为:{},仅接收key为one和two的队列的消息,入参类型为map类型,接收到的信息为:{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), map);
    }

}

 模拟生产者发送消息①

@SpringBootTest(classes = MqApplication.class)
@RunWith(SpringRunner.class)
public class ProducerDirectTest {
    @Resource
    RabbitTemplate rabbitTemplate;

    @Test
    public void sendDelayMessageByDirect() {
        rabbitTemplate.convertAndSend(
                "direct_exchange",
                "two",
                "发送消息到路由键为two的队列中"
        );
        rabbitTemplate.convertAndSend(
                "direct_exchange",
                "one",
                "发送消息到路由键为one的队列中"
        );
    }
    
}

          这段代码是使用 RabbitMQ 的 RabbitTemplate 对象来发送消息到指定的交换机和队列中。具体来说,代码中调用了两次 convertAndSend() 方法,分别向名为 direct_exchange 的直连交换机发送消息,消息内容分别为 "发送消息到路由键为two的队列中""发送消息到路由键为one的队列中",同时指定了不同的路由键。根据 RabbitMQ 的消息路由机制,这两条消息会被发送到不同的队列中,其中一条会进入名为 one 的队列,另一条则会进入名为 two 的队列。

具体来说,RabbitMQ 中的交换机(Exchange)通常用于接收生产者发送的消息,根据指定的路由键和绑定关系,将消息路由到一个或多个队列中。在本例中,使用了名为 direct_exchange 的直连交换机,它与名为 onetwo 的两个队列分别绑定,绑定关系使用路由键进行匹配。当生产者发送消息到交换机时,消息会根据指定的路由键被路由到绑定了该路由键的队列中。

        需要注意的是,如果交换机没有任何队列与其绑定,或者路由键与所有队列都没有绑定关系,那么消息将会被丢弃。因此,在使用 RabbitMQ 进行消息传递时,交换机和队列的绑定关系非常重要,需要仔细设计和管理。

 模拟生产者发送消息②

@SpringBootTest(classes = MqApplication.class)
@RunWith(SpringRunner.class)
public class ProducerDirectTest {
    @Resource
    RabbitTemplate rabbitTemplate;

    @Test
    public void sendDelayMessageByDirect() {

        rabbitTemplate.convertAndSend(
                "direct_exchange",
                "two",
                new User(24, "张三", "男")
        );

        rabbitTemplate.convertAndSend(
                "direct_exchange",
                "three",
                "发送消息到路由键为two的队列中"
        );

        Map<String, Object> map = new HashMap<>();
        map.put("name", "向天磊");
        rabbitTemplate.convertAndSend(
                "direct_exchange",
                "three",
                map
        );

        rabbitTemplate.convertAndSend(
                "direct_exchange",
                "three",
                "你好bety".getBytes()
        );

    }

}

此测试方法发送了不同的消息类型,在消费端根据不同的类型调用不同的方法 

注:一个方法中同时发送多个convertAndSend,只有第一个convertAndSend生效

启动成功之后,在RabbitMq控制面板即可看见已经自动创建好交换机和队列,并且交换机和队列已经绑定在了一起,如图1-1,1-2,1-3所示

 图1-1 消费队列

  图1-2 直连交换机

   图1-3 交换机和队列绑定图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术路上的探险家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值