RabbitMQ的交换机使用(二)

1、RabbitMQ交换机的概念

RabbitMQ传递消息的核心思想:生产者生产的消息不会直接发送到队列,只能将消息发送到交换机exchange;
交换机的工作内容很简单,一方面接收生产者发过来的消息,另一方面推送到队列中;
交换机知道如何处理接收到的消息,是把这些消息放到特定的队列还是丢弃它们,就由交换机的类型决定。

1.1、交换机的类型
  1. 直接类型(direct)
  2. 扇出类型(fanout)
  3. 标题类型(headers)
  4. 主题类型(topic)

在这里插入图片描述

1.2、直接类型(direct)默认的exchange
  /**
   * 1.发送到那个交换机
   * 2.队列名称
   * 3.其他参数 消息持久化参数:MessageProperties.PERSISTENT_TEXT_PLAIN
   * 4.要发送的消息体
   */
  channel.basicPublish("",queueName,null,message.getBytes());

消息能路由发送到队列中其实是由 routingKey(bindingkey) 绑定 key 指定的

1.3、临时队列

每次连接到RabbitMQ时,需要一个全新的空队列,我们可以创建一个具有随机名称的队列,
或者让服务器帮我们创建一个,一旦断开消费者连接,队列将自动删除

String queueName=channel.queueDeclare.getQueue();
1.4、绑定(bindings)

binding就是exchange和queue之间的桥梁,声明了那个exchange和那个队列进行了绑定关系
在这里插入图片描述

2、Fanout类型交换机

Fanout这个类型的交换机,就是将所收到的消息广播到所有绑定的队列中
在这里插入图片描述

import java.nio.charset.StandardCharsets;
import java.util.Scanner;

//Fanout交换机实例
public class Task5 {
    private static final String EXCHANGE_NAME="fanouttest1";
    public static void main(String[] args) throws Exception {
        Channel channel= ChannelUnit.getChannel();
        /**
         * 1、exchange交换机的名称
         * 2、exchange交换机的类型
         */
        channel.exchangeDeclare(EXCHANGE_NAME,BuiltinExchangeType.FANOUT);
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入信息");
        while(scanner.hasNext()){
            String message=scanner.nextLine();
            /**
             * 1.交换机exchange的名称
             * 2.队列名称
             * 3.其它参数
             * 4.要发送的消息
             */
            channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes(StandardCharsets.UTF_8));
            System.out.println("生产者发送消息:"+message);
        }
    }
}
import com.example.wwy.rabbit.units.ChannelUnit;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//消费者
public class Work3 {
    private static final String EXCHANGE_NAME="fanouttest1";

    public static void main(String[] args) throws Exception {
        Channel channel= ChannelUnit.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //产生一个临时队列
        String queueName=channel.queueDeclare().getQueue();
        /**
         * 1、队列名称
         * 2、交换机名称
         * 3、routingKey 绑定的Key
         */
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        System.out.println("W3等待接收消息。。。");

        DeliverCallback deliverCallback=(var1,var2)->{
            String message=new String(var2.getBody(),"UTF-8");
            System.out.println("W3接收到的消息是:【"+message+"】");
        };
        CancelCallback cancelCallback=(var1)->{
            System.out.println("消费消息被中断");
        };
        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}

3、Direct类型交换机

exchange 的绑定类型是direct,根据绑定routingKey去给指定的队列发送消息
但是它绑定的多个队列的 key 如果都相同,在这种情况下虽然绑定类型是 direct 但是它表现的就和 fanout 有点类似了,就跟广播差不多

在这里插入图片描述

import com.example.wwy.rabbit.units.ChannelUnit;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

//生产者
public class DirectTask1 {
    private static final String DIRECT_NAME="direct_log";

    public static void main(String[] args) throws Exception {
        Channel channel = ChannelUnit.getChannel();
        //生成一个交换机
        channel.exchangeDeclare(DIRECT_NAME, BuiltinExchangeType.DIRECT);
        //创建多个Bindingkey
        Map<String ,String> map=new HashMap<>();
        map.put("orange","信息orange");
        map.put("black","信息black");
        map.put("green","信息green");
        for(Map.Entry<String,String> a:map.entrySet()){
            String bindingkey=a.getKey();
            String message=a.getValue();
            channel.basicPublish(DIRECT_NAME,bindingkey,null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println("生产者发送消息;【"+message+"】");
        }
    }
}
import com.example.wwy.rabbit.units.ChannelUnit;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//消费者1
public class DirectWork1 {
    private static final String DIRECT_NAME="direct_log";

    public static void main(String[] args) throws Exception {
        Channel channel = ChannelUnit.getChannel();
        //设置交换机
        channel.exchangeDeclare(DIRECT_NAME, BuiltinExchangeType.DIRECT);
        String queueName="q1";
        //设置队列
        channel.queueDeclare(queueName,false,false,true,null);
        //队列绑定
        channel.queueBind(queueName,DIRECT_NAME,"orange");
        System.out.println("DW1等待接收消息。。。");
        DeliverCallback deliverCallback=(var1, var2)->{
            String message=new String(var2.getBody(),"UTF-8");
            System.out.println(message);
        };
        CancelCallback cancelCallback=(var1)->{
            System.out.println("DW1消息接收失败");
        };
        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}
import com.example.wwy.rabbit.units.ChannelUnit;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//消费者2
public class DirectWork2 {
    private static final String DIRECT_NAME="direct_log";

    public static void main(String[] args) throws Exception {
        Channel channel = ChannelUnit.getChannel();
        //设置交换机
        channel.exchangeDeclare(DIRECT_NAME, BuiltinExchangeType.DIRECT);
        String queueName="q2";
        //设置队列
        channel.queueDeclare(queueName,false,false,true,null);
        //队列绑定
        channel.queueBind(queueName,DIRECT_NAME,"black");
        channel.queueBind(queueName,DIRECT_NAME,"green");
        System.out.println("DW2等待接收消息。。。");
        DeliverCallback deliverCallback=(var1, var2)->{
            String message=new String(var2.getBody(),"UTF-8");
            System.out.println(message);
        };
        CancelCallback cancelCallback=(var1)->{
            System.out.println("DW2消息接收失败");
        };
        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}

4、Topics类型交换机

发送到类型是 topic 交换机的消息的 routing_key 不能随意写,必须满足一定的要求,它必须是一个单词列表,以点号分隔开
这些单词可以是任意单词,比如说:“stock.usd.nyse”, “nyse.vmw”,“quick.orange.rabbit”.这种类型的。当然最多不能超过 255 个字节。

引入了两个替换符
*(星号)可以代替一个单词
#(井号)可以替代零个或多个单词

在这里插入图片描述

import com.example.wwy.rabbit.units.ChannelUnit;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

//生产者
public class TopicsTask1 {
    private static final String DIRECT_NAME="topics_log";

    public static void main(String[] args) throws Exception {
        Channel channel = ChannelUnit.getChannel();
        //生成一个交换机
        channel.exchangeDeclare(DIRECT_NAME, BuiltinExchangeType.TOPIC);

        //创建多个Bindingkey
        Map<String ,String> map=new HashMap<>();
        map.put("quick.orange.rabbit","被队列 Q1Q2 接收到");
        map.put("lazy.orange.elephant","被队列 Q1Q2 接收到");
        map.put("quick.orange.fox","被队列 Q1 接收到");
        map.put("lazy.brown.fox","被队列 Q2 接收到");
        map.put("lazy.pink.rabbit","虽然满足两个绑定但只被队列 Q2 接收一次");
        map.put("quick.brown.fox","不匹配任何绑定不会被任何队列接收到会被丢弃");
        map.put("quick.orange.male.rabbit","是四个单词不匹配任何绑定会被丢弃");
        map.put("lazy.orange.male.rabbit","是四个单词但匹配 Q2");

        for(Map.Entry<String,String> a:map.entrySet()){
            String bindingkey=a.getKey();
            String message=a.getValue();
            channel.basicPublish(DIRECT_NAME,bindingkey,null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println("生产者发送消息;【"+message+"】");
        }
    }
}
import com.example.wwy.rabbit.units.ChannelUnit;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//消费者1
public class TopicsWork1 {
    private static final String DIRECT_NAME="topics_log";

    public static void main(String[] args) throws Exception {
        Channel channel = ChannelUnit.getChannel();
        //设置交换机
        channel.exchangeDeclare(DIRECT_NAME, BuiltinExchangeType.TOPIC);
        String queueName="q1";
        //设置队列
        channel.queueDeclare(queueName,false,false,true,null);
        //队列绑定
        channel.queueBind(queueName,DIRECT_NAME,"*.orange.*");
        System.out.println("DW1等待接收消息。。。");
        DeliverCallback deliverCallback=(var1, var2)->{
            String message=new String(var2.getBody(),"UTF-8");
            System.out.println(message);
        };
        CancelCallback cancelCallback=(var1)->{
            System.out.println("DW1消息接收失败");
        };
        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}

import com.example.wwy.rabbit.units.ChannelUnit;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//消费者2
public class TopicsWork2 {
    private static final String DIRECT_NAME="topics_log";

    public static void main(String[] args) throws Exception {
        Channel channel = ChannelUnit.getChannel();
        //设置交换机
        channel.exchangeDeclare(DIRECT_NAME, BuiltinExchangeType.TOPIC);
        String queueName="q2";
        //设置队列
        channel.queueDeclare(queueName,false,false,true,null);
        //队列绑定
        channel.queueBind(queueName,DIRECT_NAME,"*.*.rabbit");
        channel.queueBind(queueName,DIRECT_NAME,"lazy.#");
        System.out.println("DW2等待接收消息。。。");
        DeliverCallback deliverCallback=(var1, var2)->{
            String message=new String(var2.getBody(),"UTF-8");
            System.out.println(message);
        };
        CancelCallback cancelCallback=(var1)->{
            System.out.println("DW2消息接收失败");
        };
        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}

小结,交换机主要是根据BindingKey去给对应的队列传输消息。

  1. Fanout 广播类型:无需bindingkey,只要与交换机绑定的队列都会收到消息
  2. Direct 直接类型:根据具体的bindkey,交换机给绑定的队列发送消息
  3. Topic 主题类型:bindkey类似于模拟查询。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值