初学RabbitMQ(二),初识扇形交换机与主题交换机

在上节中,说了RabbitMQ安装与其流程图以及直连交换机的用法与逻辑。本节,主要学习扇形交换机与主题交换机的用法。

初学RabbitMQ(一),使用SpringBoot进行简单的整合,初识直连交换机。


扇形交换机 amq.fanout

 amq.fanout是RabbitMQ中默认的扇形交换机的名字,可以直接绑定该交换机,也可以自定义一个扇形交换机,再创建队列进行绑定。
 可以会用多个队列绑定一个扇形交换机,消费者消费其中的数据时,会拉取扇形交换机中绑定的所有队列。

理解了扇形交换机,那么就编写一下生产者mqproducer的代码,pom的依赖文件如下:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

对应的配置文件为:

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutConfig {
    @Bean
    Queue firstQueue(){
        return new Queue("firstFanoutQueue",true);
    }

    @Bean
    Queue secondQueue(){
        return new Queue("secondFanoutQueue",true);
    }

    @Bean
    Queue thirdQueue(){
        return new Queue("thirdFanoutQueue",true);
    }

    @Bean
    Binding bindingFirstExchange(){
        return BindingBuilder.bind(firstQueue()).to(new FanoutExchange("amq.fanout"));
    }

    @Bean
    Binding bindingSecondExchange(){
        return BindingBuilder.bind(secondQueue()).to(new FanoutExchange("amq.fanout"));
    }

    @Bean
    Binding bindingThirdExchange(){
        return BindingBuilder.bind(thirdQueue()).to(new FanoutExchange("amq.fanout"));
    }
}

简单的发送消息的方法为(需要根据场景进行消息发送):

@RequestMapping("/sendtofanout")
public void sendToFanout(){
    try{
        String uuid = String.valueOf(UUID.randomUUID());
        String message = "This is a first message to Fanout!";
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
        Map<String,Object> m = new HashMap<>();
        m.put("messageId", uuid);
        m.put("createTime",date);
        m.put("message",message);
        rabbitTemplate.convertAndSend("amq.fanout",null,m);
    }catch(Exception e){
        e.printStackTrace();
    }
}

启动项目后,访问http://localhost:15672/会发现,定义的三个队列都绑定到了amq.fanout交换机上,调用发送接口后就会发现,每个队列都有一条消息正在等待消费。
在这里插入图片描述
此刻开始编写消费者的代码,其中配置文件如下(消费者可以不写,因为消费者是获取消息的主体,使用后面的注解监听器就好了,若配置了配置文件,这消费者也可以当成是发送消息的主体。

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomerFanoutConfig {
    @Bean
    Queue firstQueue(){
        return new Queue("firstFanoutQueue",true);
    }

    @Bean
    Queue secondQueue(){
        return new Queue("secondFanoutQueue",true);
    }

    @Bean
    Queue thirdQueue(){
        return new Queue("thirdFanoutQueue",true);
    }

    @Bean
    Binding bindingFirstExchange(){
        return BindingBuilder.bind(firstQueue()).to(new FanoutExchange("amq.fanout"));
    }

    @Bean
    Binding bindingSecondExchange(){
        return BindingBuilder.bind(secondQueue()).to(new FanoutExchange("amq.fanout"));
    }

    @Bean
    Binding bindingThirdExchange(){
        return BindingBuilder.bind(thirdQueue()).to(new FanoutExchange("amq.fanout"));
    }
}

接下来编写三个消息监听器,用于监听三个队列的数据,便于学习:

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
@RabbitListener(queues = {"firstFanoutQueue"})
public class CustomerFanoutFirstListener {

    @RabbitHandler
    public void process(Map m){
        System.out.println("CustomerFanoutFirstListener接受到的消息为:"+m.toString());
    }
}
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.util.Map;

@Component
@RabbitListener(queues = {"secondFanoutQueue"})
public class CustomerFanoutSecondListener {

    @RabbitHandler
    public void process(Map m){
        System.out.println("CustomerFanoutSecondListener接受到的消息为:"+m.toString());
    }
}

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
@RabbitListener(queues = {"thirdFanoutQueue"})
public class CustomerFanoutThirdListener {
    @RabbitHandler
    public void process(Map m){
        System.out.println("CustomerFanoutThirdListener接受到的消息为:"+m.toString());
    }
}

此时启动消费者项目后,每个监听器都会监听到一个消息
在这里插入图片描述
此时若是再访问一下发送消息的接口,消费者也会实时的进行消费:
在这里插入图片描述

主题交换机 amq.topic

 amq.topic是RabbitMQ中默认的主题交换机的名字,可以直接绑定该交换机,也可以自定义一个主题交换机,再创建队列进行绑定。
 主题交换机中,绑定的路由值可以使用匹配符进行模糊匹配。

#号表示的是匹配0个或者多个
*号表示的是匹配1个或者多个
举个例子:
若有路由值设定为:topic.man、topic.#
那么若有消费者携带的路由键为,那么topic.woman则可以消费成功。

那么开始编写生产者mqproducer代码,其配置类如下:
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TopicConfig {
    @Bean
    Queue topicQueue(){
        return new Queue("topic.man",true);
    }

    @Bean
    Queue topicQueue1(){
        return new Queue("topic.woman",true);
    }
    @Bean
    Binding bindingTopicExchange2(){
        return BindingBuilder.bind(topicQueue()).to(new TopicExchange("amq.topic")).with("topic.man");
    }
    @Bean
    Binding bindingTopicExchange1(){
        return BindingBuilder.bind(topicQueue1()).to(new TopicExchange("amq.topic")).with("topic.#  ");
    }
}

接下来写一下简单的发送消息的接口:

 @RequestMapping("/sendtotopic1")
    public void sendToTopicMan(){
        try{
            String uuid = String.valueOf(UUID.randomUUID());
            String message = "This is a first message to topic : Man!";
            String date = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
            Map<String,Object> m = new HashMap<>();
            m.put("messageId", uuid);
            m.put("createTime",date);
            m.put("message",message);
            rabbitTemplate.convertAndSend("amq.topic","topic.man",m);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @RequestMapping("/sendtotopic2")
    public void sendToTopicWoman(){
        try{
            String uuid = String.valueOf(UUID.randomUUID());
            String message = "This is a first message to topic : Woman!";
            String date = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
            Map<String,Object> m = new HashMap<>();
            m.put("messageId", uuid);
            m.put("createTime",date);
            m.put("message",message);
            rabbitTemplate.convertAndSend("amq.topic","topic.asdasd",m);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

现在开始编写一下消费者的代码,配置文件如下(可以不用写):

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomerTopicConfig {
    @Bean
    Queue topicQueue(){
        return new Queue("topic.man",true);
    }

    @Bean
    Queue topicQueue1(){
        return new Queue("topic.woman",true);
    }
    @Bean
    Binding bindingTopicExchange2(){
        return BindingBuilder.bind(topicQueue()).to(new TopicExchange("amq.topic")).with("topic.man");
    }
    @Bean
    Binding bindingTopicExchange1(){
        return BindingBuilder.bind(topicQueue1()).to(new TopicExchange("amq.topic")).with("topic.#  ");
    }
}

监听消息的代码如下,需要建两个监听类,一个监听topic.man一个监听topic.woman两个队列:

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
@RabbitListener(queues = {"topic.man"})
public class CustomerTopicFirstListener {

    @RabbitHandler
    public void process(Map m){
        System.out.println("CustomerTopicFirstListener接受到的消息为:"+m.toString());
    }
}

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
@RabbitListener(queues = {"topic.woman"})
public class CustomerTopicSecondListener {

    @RabbitHandler
    public void process(Map m){
        System.out.println("CustomerTopicSecondListener接受到的消息为:"+m.toString());
    }
}

此刻启动生产者项目和消费者项目,访问RabbitMQ服务端就可以发现了,队列已经与主题交换机绑定好了,此时访问sendtotopic1接口,可以发现两个队列都接受到了消息,说明路由键匹配上了。
在这里插入图片描述
这时候,访问一下sendtotopic2接口,可以发现只有topic.woman的队列匹配上了。
在这里插入图片描述
在sendtotopic2接口代码中,我携带的路由键是topic.asdasd,这就是匹配符的作用,句点之后无论写什么,都能匹配到路由值topic.#绑定的队列上。


主题交换机是很强大的,为什么呢?


这是因为主题交换机可以做为直连交换机或者扇形交换机的使用。
若绑定的路由键直接设置为#号,则默认任何消息携带的任何路由键都能匹配,可以作为扇形交换机使用。
若绑定的路由键不包含#号和*号,就可以作为直连交换机使用。


本节记录了主题交换机与扇形交换机的用法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值