Spring Boot RabbitMQ 入门(四)之 Topic交换器

0.回顾


Spring Boot RabbitMQ 入门(三)之 Fanout交换器
上篇文章我们学习了以下几点:
* 1.如何创建消息生产者
* 2.如何使用消息生产者发送消息
* 3.如何定义Fanout交换器
* 4.将对列绑定到交换器从而测试其特性

1.Topic交换器介绍


Spring Boot RabbitMQ 入门(四)之 Topic交换器_第1张图片
如上图所示
此类交换器使得来自不同的源头的消息可以到达一个对列,其实说的更明白一点就是模糊匹配的意思,例如:上图中红色对列的routekey为usa.#,#代表匹配任意字符,但是要想消息能到达此对列,usa.必须匹配后面的#好可以随意。图中usa.news usa.weather,都能找到红色队列,符号“#”匹配一个或多个词,符号“”匹配不多不少一个词。因此“usa.#”能够匹配到“usa.news.XXX”,但是“usa.” 只会匹配到“usa.XXX”。
注:
交换器说到底是一个名称与队列绑定的列表。当消息发布到交换器时,实际上是由你所连接的信道,将消息路由键同交换器上绑定的列表进行比较,最后路由消息

2.Topic交换器实践


2.1创建交换器


 @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(EXCHANGE);
    }

2.2创建队并


 @Bean
    public Queue queue() {
        return new Queue("spring-queue", true); //队列持久
    }
    @Bean
    public Queue queue2() {
        return new Queue("spring-queue2", true); //队列持久
    }

2.3对列绑定并关联到ROUTINGKEY

此处要理解Topic交换器介绍中的注部分就明白
两个对列分别匹配两个不同规则

public static final String EXCHANGE   = "spring-topic-exchange";
    public static final String ROUTINGKEY1 = "weather-routingKey.*";
    public static final String ROUTINGKEY2 = "msg-routingKey.#";
    @Bean
    public Binding binding() {
        return BindingBuilder.bind(queue()).to(topicExchange()).with(ROUTINGKEY1);
    }
    @Bean
    public Binding binding2() {
        return BindingBuilder.bind(queue2()).to(topicExchange()).with(ROUTINGKEY2);
    }

2.4创建消费者,分别消费两对列


Bean
    public SimpleMessageListenerContainer messageContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
        container.setQueues(queue());
        container.setExposeListenerChannel(true);
        container.setMaxConcurrentConsumers(1);
        container.setConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
        container.setMessageListener(new ChannelAwareMessageListener() {
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                byte[] body = message.getBody();
                          System.out.println("receive msg queue: " + new String(body));
                          Thread.sleep(10000);

                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费

            }
        });
        return container;
    }

    @Bean
    public SimpleMessageListenerContainer messageContainer2() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
        container.setQueues(queue2());
        container.setExposeListenerChannel(true);
        container.setMaxConcurrentConsumers(1);
        container.setConcurrentConsumers(1);
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
        container.setMessageListener(new ChannelAwareMessageListener() {
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                byte[] body = message.getBody();
                System.out.println("receive msg queue2: " + new String(body));
                Thread.sleep(10000);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费


            }
        });
        return container;
    }

2.5消息生产者生产消息


@Autowired
    RabbitTemplate template;
    public void send(String context) {
        template.convertAndSend(RabbitConfig.EXCHANGE, "weather-routingKey.a", context);

    }

2.验证


此处为了方便验证就不采用发送者发送了,直接用RabbitMQ管理端进行发送
* 1情况一

Spring Boot RabbitMQ 入门(四)之 Topic交换器_第2张图片
我们匹配对列2的msg-routingKey.#
输出结果如下
预计情况会queue2对列消费者消费消息

receive msg queue2: 21213
  • 2情况二
    我们前文讲到采用#可以匹配多个字符
    我们使用routingKey =msg-routingKey.a.b如果前文正确,则
    输出结果如下
receive msg queue2: msg-routingKey.a.b
  • 3.情况三
    *匹配只能是单个字符所以我们我们使用routingKey =weather-routingKey.a如果前文正确,则输出对列queue接受到消息
    结果如下:
receive msg queue: weather-routingKey.a
  • 4.情况四
    我们模拟*匹配“多个字符”的情况routingKey =weather-routingKey.a.b
    如果前文正确,则消息会进入消息”黑洞”,被丢弃,没有输出。
    结果如下:
.

最后

注:此处的多个字符是指以”.”间隔为一个。
Direct其实就是要求routingKey 完全匹配,所以就不再赘述

你可能感兴趣的:(Spring)