RabbitMQ学习记录

使用spring boot整合RabbitMQ,构建多模块工程学习rabbitMQ使用,学习记录如下:

搭建spring-boot多模块工程:

分别演示,RabbitMQ的工作模式:

第一种:

Direct Exchange
Direct Exchange是RabbitMQ默认的交换机模式,也是最简单的模式,根据key全文匹配去寻找队列。

这种工作模式,使用默认交换机,在生产者在发送消息时,直接指定队列名称,将消息发送到指定的队列中,消费者,在接受消息时,指定监听某一指定的队列。

代码演示如下:

公共初始化代码:

首先,在公共工程common,创建RabbitmqConfig类,此类主要用于项目初始化时,创建必要的bean,比如,创建队列,交换机,交换机绑定队列等。

@Configuration
public class RabbitmqConfig {
    @Bean
    public Queue Queue() {
        return new Queue("hello");
    }
}

使用@configation注解,默认初始化是创建里面声明的对象,注意要在,启动类开启扫描该包;@ComponentScan(...)

@SpringBootApplication
@ComponentScan(basePackages={"com.yunda.sb.rmq"})//扫描本项目下的所有类
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication .class, args);
    }
}

生产者代码:

在producer工程下,创建测试类:

使用测试类,发送消息,注入RabbitTemplate,使用convertAndSend方法,指定队列名称,和消息内容。也可以发送实体对象,但是实体类需要实现序列化接口。

@SpringBootTest
@RunWith(SpringRunner.class)
public class RMQProducerTest {

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    public void send() {

     //   User user = new User("张三",18 );
     //   this.rabbitTemplate.convertAndSend("hello", user);
        String context = "hello " + new Date();
        System.out.println("Sender : " + context);
//注意第一个参数,队列名称,第二个参数,消息内容
        this.rabbitTemplate.convertAndSend("hello", context);
    }

}

在consumer工程下,创建类,用于监听队列消息

消费者代码:

注意启动类扫描到该包下,创建该监听类,方法上指定监听的队列名称,

@Component
public class ReceiveHandler {

    @RabbitListener(queues = "hello")
    public void process(String hello) {
        System.out.println("Receiver  : " + hello);
    }
  /*  @RabbitListener(queues = "hello")
    public void process(User user) {
        System.out.println("Receiver  : " + user.toString());
    }*/
}

另一中写法:一个类监听一个队列的方法。

@Component
@RabbitListener(queues = "hello")
public class ReceiveHandler {

    @RabbitHandler
    public void process(String hello) {
        System.out.println("Receiver  : " + hello);
    }
}

第二种:fanout

发布订阅模式,广播模式生产者将消息发送给交换机,交换机会把这个消息,发给每一个绑定到该交换机的队列,即一对多

                                                                    

代码演示如下:

公共初始化代码:

公共common,配置类初始化,声明交换机,队列,绑定队列与交换机,注意指定的交换机类型,为FanoutExchange,这里使用创建队列方式,一个声明常量方式,另一种直接在注解,使用字符串作为队列名称,注意,在绑定队列到交换机传入的参数,是FanoutExchange。

@Configuration
public class RabbitmqConfigFanout {
    //交换机名称
    public static final String EXCHANGE_TOPICS_INFORM="fanoutExchange";
    //队列名称
    public static final String QUEUE_INFORM_EMAIL = "queue01";
    public static final String QUEUE_INFORM_SMS = "queue02";
    /**
     * 交换机配置
     * ExchangeBuilder提供了fanout、direct、topic、header交换机类型的配置
     * @return the exchange
     */
    @Bean(EXCHANGE_TOPICS_INFORM)
    public FanoutExchange EXCHANGE_TOPICS_INFORM() {
        //durable(true)持久化,消息队列重启后交换机仍然存在
        //注意在这里指定的交换机类型,是fanout
        return new FanoutExchange(EXCHANGE_TOPICS_INFORM);
    }
    //声明队列
    @Bean(QUEUE_INFORM_SMS)
    public Queue QUEUE_INFORM_SMS() {
        Queue queue = new Queue(QUEUE_INFORM_SMS);
        return queue;
    }
    //声明队列
    @Bean(QUEUE_INFORM_EMAIL)
    public Queue QUEUE_INFORM_EMAIL() {
        Queue queue = new Queue(QUEUE_INFORM_EMAIL);
        return queue;
    }
    //声明队列
    @Bean("queue03")  //队列名称
    public Queue QUEUE_03() {
        Queue queue = new Queue("queue03");
        return queue;
    }
    /**
     * 绑定队列到交换机
     * @param queue the queue
     * @param exchange the exchange
     * @return the binding
     */
    @Bean
    public Binding bindQueue01(@Qualifier(QUEUE_INFORM_SMS) Queue queue,
                                            @Qualifier(EXCHANGE_TOPICS_INFORM) FanoutExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange);
    }
    @Bean
    public Binding bindQueue02(@Qualifier(QUEUE_INFORM_EMAIL) Queue queue,
                                              @Qualifier(EXCHANGE_TOPICS_INFORM) FanoutExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange);
    }

    @Bean
    public Binding bindQueue03(@Qualifier("queue03") Queue queue,
                                              @Qualifier(EXCHANGE_TOPICS_INFORM) FanoutExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange);
    }

如上图,打开rabbit管理界面,找到创建的交换机,绑定的3个队列如上。

生产者代码:

在producer工程下,的测试类,中加入发送消息的测试方法,注意,这里的发送方法的参数,第一个,交换机名称,第二个路由键,默认给空串,第三个消息的内容。

@Test
    public void send2() {
        String context = "hi, fanout msg ==========> ";
        //注意这里是3个参数,第1个交换机名称,第2个路由键默认为空,第3个为消息内容。
        this.rabbitTemplate.convertAndSend("fanoutExchange","", context);
        System.out.println("Sender : " + context);
// this.rabbitTemplate.convertAndSend(RabbitmqConfigFanout.EXCHANGE_TOPICS_INFORM,"", context);
    }

消费者代码:

在consumer工程下,创建消息监听类,ReceiveHandlerFanout,分别监听三个队列,

@Component
public class ReceiveHandlerFanout {

      @RabbitListener(queues = "queue01")
      public void receive_queue01( String message){
          System.out.println(message);
    }
    @RabbitListener(queues = "queue02")
    public void receive_queue02( String message){
        System.out.println(message);
    }
    @RabbitListener(queues = "queue03")
    public void receive_queue03( String message){
        System.out.println(message);
    }

}

 

第三种方式:Routing模式

交换机为direct模式,队列绑定交换机,并指定路由键,生产者,发送消息到交换机,并同时给出了路由键,交换机根据给过来的路由键,将消息,放到相应得到队列中去。

                             

代码演示如下:

公共工程common下,创建RabbitmqConfigRouting配置类,初始化创建交换机,队列,队列绑定交换机并指定路由键,代码如下:注意交换机类型为,DirectExchange

@Component
public class RabbitmqConfigRouting {

    /**第一步,创建交换机
     * 交换机配置
     * ExchangeBuilder提供了fanout、direct、topic、header交换机类型的配置
     */
    @Bean("routingExchange")
    public DirectExchange creatRoutingExchange() {
        //durable(true)持久化,消息队列重启后交换机仍然存在
        //注意在这里指定的交换机类型,是fanout
        return new DirectExchange("routingExchange");
    }
    /**第二步,创建队列
     * 指定队列名称,bean名称
     */

    //声明队列
    @Bean("queueAA")  //队列名称
    public Queue QUEUE_AA() {
        Queue queue = new Queue("queueAA");
        return queue;
    }

    //声明队列
    @Bean("queueBB")  //队列名称
    public Queue QUEUE_BB() {
        Queue queue = new Queue("queueBB");
        return queue;
    }

    /**
     * 第三步,队列绑定交换机,并指定绑定规则,即说明绑定的路由规则
     * 传入参数,交换机和队列
     */
    @Bean
    public Binding BINDING_QUEUE_AA(@Qualifier("queueAA") Queue queue,
                                            @Qualifier("routingExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("AA");
    }

    @Bean
    public Binding BINDING_QUEUE_BB(@Qualifier("queueBB") Queue queue,
                                            @Qualifier("routingExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("BB");
    }

}

启动项目,打开管理页面,发现,已经创建了交换机并绑定了对应的队列如下图,对比上述代码。交换机名称,队列名称,路由键。

                                                            

生产者代码:

在producer工程的测试类中,继续创建发送消息的方法,如下,指定路由键,

代码如下:

   @Test
    public void sendAA() {
        String context = "hi AA, this is  msg to AA queue ";
        //注意这里是3个参数,第1个交换机名称,第2个路由键,第3个为消息内容。
        this.rabbitTemplate.convertAndSend("routingExchange","AA", context);
        System.out.println("Sender : " + context);
    }
    @Test
    public void sendBB() {
        String context = "hi BB, this is  msg to BB queue ";
        //注意这里是3个参数,第1个交换机名称,第2个路由键,第3个为消息内容。
        this.rabbitTemplate.convertAndSend("routingExchange","BB", context);
        System.out.println("Sender : " + context);
    }

 

消费者代码:

在consumer工程下,创建类ReceiveHandlerRouting,用于监听这个2个队列,

@Component
public class ReceiveHandlerRouting {

    @RabbitListener(queues = "queueAA")//监听队列AA
    public void receive_queueAA( String message){
        System.out.println("Receiver A "+message);
    }
    @RabbitListener(queues = "queueBB") //监听队列BB
    public void receive_queueBB( String message){
        System.out.println("Receiver B "+message);
    }
}

分别测试,向AA队列,BB队列发送消息,测试成功。

 

第四种方式  Topics

            Topics 话题模式或者主题模式,这种模式下,交换机的类型为topic,队列绑定交换机的时候,不再是一个确定的路由键,而是带通配符的路由模式,生产者在发送消息时,会指定一个具体的路由键,交换机拿到这个路由键后,去匹配跟它绑定队列的路由模式,如果,匹配上这个路由键,就会把这个消息投递到这队列中,主要匹配上就会投递,所有,一条消息,可以投递到多个队列中去,只要这些队列满足匹配规则。

                

 

代码演示如下:

公共配置类,在common工程下,创建初始化配置类,RabbitmqConfigTopics,指定交换机类型,创建队列,队列绑定交换机并指定路由模式。代码入下:

@Component
public class RabbitmqConfigTopics {
    /**第一步,创建交换机
     * 交换机配置
     * ExchangeBuilder提供了fanout、direct、topic、header交换机类型的配置
     */
    @Bean("topicsExchange")
    public TopicExchange createTopExchange() {
        //durable(true)持久化,消息队列重启后交换机仍然存在
        //注意在这里指定的交换机类型,是topic
        return new TopicExchange("topicsExchange");
    }
    /**第二步,创建队列
     * 指定队列名称,bean名称
     */
    @Bean("topicA")
    public Queue QueueA() {
        return new Queue("topicA");
    }

    @Bean("topicB")
    public Queue QueueB() {
        return new Queue("topicB");
    }
    /**
     * 第三步,队列绑定交换机,并指定绑定规则,
     * 绑定规则为指定路由模式,不是一个固定的路由键
     * 传入参数,交换机和队列
     */
    @Bean
    public Binding BINDING_QUEUE_Topic_A(@Qualifier("topicA") Queue queue,
                                            @Qualifier("topicsExchange") TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("topic.#.A.*");
    }
    @Bean
    public Binding BINDING_QUEUE_Topic_B(@Qualifier("topicB") Queue queue,
                                              @Qualifier("topicsExchange") TopicExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("topic.*.B.#");
    }
}

启动项目,打开管理页面,观察创建好的交换机,队列,及路由模式

                                                        

生产者代码:

在producer工程下的测试类中创建测试方法,注意模式的匹配。

在发消息是,指定具体的路由键,交换机拿到路由键去匹配路由模式,匹配成功,就进行投递消息到队列

 //*表示一个词.
    //  #表示零个或多个词.
    @Test
    public void sendTopicA() {
        String context = "hi TopicA, 这个消息只能由A队列接受 ";
        //注意这里是3个参数,第1个交换机名称,第2个路由键,第3个为消息内容 topicA的路由模式,topic.#.A.*
        this.rabbitTemplate.convertAndSend("topicsExchange","topic.A.info", context);
        System.out.println("Sender : " + context);
    }
    @Test
    public void sendTopicB() {
        String context = "hi TopicB, 这个消息只能由B队列接受";
        //注意这里是3个参数,第1个交换机名称,第2个路由键,第3个为消息内容。topicB的路由模式,topic.*.B.#
        this.rabbitTemplate.convertAndSend("topicsExchange","topic.info.B", context);
        System.out.println("Sender : " + context);
    }
    @Test
    public void sendTopicC() {
        String context = "hi TopicA and TopicB , 这个消息可以由A队列,B队列接受";
        //注意这里是3个参数,第1个交换机名称,第2个路由键,第3个为消息内容。
        this.rabbitTemplate.convertAndSend("topicsExchange","topic.A.B", context);
        System.out.println("Sender : " + context);
    }

 

消费者代码:

在consumer工程下创建监听类ReceiveHandlerTopics,获取队列消息,

@Component
public class ReceiveHandlerTopics {
    @RabbitListener(queues = "topicA")//监听队列topicA
    public void receive_queueAA( String message){
        System.out.println("Receiver: topicA ,我获取到消息:"+message);
    }
    @RabbitListener(queues = "topicB") //监听队列topicB
    public void receive_queueBB( String message){
        System.out.println("Receiver: topicB,我获取到消息:"+message);
    }
}

分别发送消息,测试成功。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值