SpringBoot集成RabbitMQ高级使用

 

1.交换器

发消息者、队列、收消息者,RabbitMQ 在这三个基本概念之上, 做了一层抽象, 在发消息者和 队列之间, 加入了交换器 (Exchange). 这样发消息者和队列就没有直接联系, 转而变成发消息者把消息给交换器, 交换器根据调度策略再把消息再给队列。

                                               SpringBoot集成RabbitMQ高级使用_第1张图片

P 代表生产者,X代表交换器,后边是队列,C代表消费者。

其中中间一层server可以称为虚拟主机。

  • 虚拟主机:一个虚拟主机持有一组交换机、队列和绑定。为什么需要多个虚拟主机呢?很简单,RabbitMQ当中,用户只能在虚拟主机的粒度进行权限控制。 因此,如果需要禁止A组访问B组的交换机/队列/绑定,必须为A和B分别创建一个虚拟主机。每一个RabbitMQ服务器都有一个默认的虚拟主机“/”。

  • 交换机:Exchange 用于转发消息,但是它不会做存储 ,如果没有 Queue bind 到 Exchange 的话,它会直接丢弃掉 Producer 发送过来的消息。
    这里有一个比较重要的概念:路由键 。消息到交换机的时候,交互机会转发到对应的队列中,那么究竟转发到哪个队列,就要根据该路由键。

  • 绑定:也就是交换机需要和队列相绑定,这其中如上图所示,是多对多的关系

    交换机的功能主要是接收消息并且转发到绑定的队列,交换机不存储消息,在启用ack模式后,交换机找不到队列会返回错误。交换机有四种类型:Direct, topic, Headers and Fanout

  • Direct:direct 类型的行为是”先匹配, 再投送”. 即在绑定时设定一个 routing_key, 消息的routing_key 匹配时, 才会被交换器投送到绑定的队列中去.

  • Topic:按规则转发消息(最灵活)

  • Headers:设置header attribute参数类型的交换机

  • Fanout:转发消息到所有绑定队列

代码实现

Topic模式

新建两个queue和一个topic交换器,并且,两个队列绑定到交换器上。

package com.haval.demo.mq;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
@Configuration
public class TopicRabbitConfig {
	final static String message = "topic.queue";  
    final static String messages = "topic.queues";
    @Bean
    public Queue queueMessage() {        
       return new Queue(TopicRabbitConfig.message);
    }
    @Bean
    public Queue queueMessages() {        
       return new Queue(TopicRabbitConfig.messages);
    }
    @Bean
    TopicExchange exchange() {        
       return new TopicExchange("exchange");
    }
    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {        
       return BindingBuilder.bind(queueMessage).to(exchange).with("topic.queue");
    }
    @Bean
    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {        
       return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }
}

然后定义两个消息发送的方法

public void sendMessage() {
    	for (int i = 0; i < 100; i++) {
        	String context = "Message " + new Date()+"-------"+String.valueOf(i);
            System.out.println("Sender : " + context);
        	this.rabbitTemplate.convertAndSend("exchange",TopicRabbitConfig.message, context);
    	}
        
    }
    public void sendMessages() {
    	for (int i = 0; i < 100; i++) {
    		String context = "Messages " + new Date()+"---s----"+String.valueOf(22);
            System.out.println("Sender : s " + context);
        	this.rabbitTemplate.convertAndSend("exchange",TopicRabbitConfig.messages, context);
		}
        	
    }

然后定义两个,队列的监听器

@Component
@RabbitListener(queues = TopicRabbitConfig.message)
public class TopicMessageReceiver {
	@RabbitHandler
    public void process(String hello) {
        System.out.println("我是处理消息的111" + hello);
    }
}


@Component
@RabbitListener(queues = TopicRabbitConfig.messages)
public class TopicMessagesReceiver {
	@RabbitHandler
    public void process(String hello) {
		 System.out.println("我是处理消息的222" + hello);
    }
}

当执行sendMessage()的时候,两个队列都能收到消息,当执行sendMessages()的时候,只有queues能收到消息。

Fanout Exchange就是发布和订阅模式,给Fanout交换机发送消息,绑定了这个交换机的所有队列都收到这个消息。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.amqp.core.TopicExchange;
@Configuration
public class FanoutRabbitConfig {
	final static String Fanoutqueue1 = "Fanout.queue1";  
    final static String Fanoutqueue2 = "Fanout.queue2";
    final static String Fanoutqueue3 = "Fanout.queue3";
    @Bean
    public Queue Fanoutqueue1() {        
       return new Queue(FanoutRabbitConfig.Fanoutqueue1);
    }
    @Bean
    public Queue Fanoutqueue2() {        
       return new Queue(FanoutRabbitConfig.Fanoutqueue2);
    }
    @Bean
    public Queue Fanoutqueue3() {        
       return new Queue(FanoutRabbitConfig.Fanoutqueue3);
    }
    @Bean
    public FanoutExchange FanoutExchange() {        
       return new FanoutExchange("FanoutExchange");
    }
    @Bean
    Binding bindingExchange1(Queue Fanoutqueue1, FanoutExchange FanoutExchange) {        
       return BindingBuilder.bind(Fanoutqueue1).to(FanoutExchange);
    }
    @Bean
    Binding bindingExchange2(Queue Fanoutqueue2, FanoutExchange FanoutExchange) {        
       return BindingBuilder.bind(Fanoutqueue2).to(FanoutExchange);
    }
    @Bean
    Binding bindingExchange3(Queue Fanoutqueue3, FanoutExchange FanoutExchange) {        
       return BindingBuilder.bind(Fanoutqueue3).to(FanoutExchange);
    }
}
public void sendFanout(){
	        String context = "hi, fanout msg ";
	        System.out.println("Sender : " + context);       
	        this.rabbitTemplate.convertAndSend("FanoutExchange","", context);
	}

在绑定三个监听器

@Component
@RabbitListener(queues = FanoutRabbitConfig.Fanoutqueue1)
public class FanoutMessageReceiver1 {
	@RabbitHandler
    public void process(String hello) {
        System.out.println("我是处理消息的1" + hello);
    }
}
Sender : hi, fanout msg 
我是处理消息的1hi, fanout msg 
我是处理消息的2hi, fanout msg 
我是处理消息的3hi, fanout msg 

三个队列都会收到消息

你可能感兴趣的:(Spring,Boot)