Spring Boot RabbitMQ 入门(四)之 Topi

2017-02-16  本文已影响781人  5d44bc28b93d

0.回顾


Spring Boot RabbitMQ 入门(三)之 Fanout交换器
上篇文章我们学习了以下几点:

1.Topic交换器介绍


Topic.png
如上图所示
此类交换器使得来自不同的源头的消息可以到达一个对列,其实说的更明白一点就是模糊匹配的意思,例如:上图中红色对列的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管理端进行发送

f.png

我们匹配对列2的msg-routingKey.#
输出结果如下
预计情况会queue2对列消费者消费消息

receive msg queue2: 21213
receive msg queue2: msg-routingKey.a.b
receive msg queue: weather-routingKey.a
.

最后

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

上一篇 下一篇

猜你喜欢

热点阅读