RabbitMQ:交换机

交换机在使用前都需要绑定(bindings)队列,什么是 binding 呢,binding 其实是 exchange 和 queue 之间的桥梁,它告诉我们 exchange 和哪个队列进行了绑定关系。

绑定关系介绍:

一、Fanout(扇出交换机)
Fanout 这种类型非常简单。它将接收到的所有消息广播到它知道的所有队列中(RoutingKey一致的情况下)。通俗点说,使用了扇出(Fanout)类型的交换机可以将消息转发到所有它绑定的队列中,每一个队列都可接收到消息。

代码:

生产者:

package com.run.rabbitmq.five;

import com.rabbitmq.client.Channel;
import com.run.rabbitmq.utils.RabbitMqUtils;

import java.util.Scanner;

/**
 * @Date: 2021/07/07/9:56
 *
 *
 *  发消息 交换机
 */
public class EmitLog {

    //交换机的名称
    public static final String EXCHANGER_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明交换机类型
        channel.exchangeDeclare(EXCHANGER_NAME,"fanout");

        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNext()){
            String message = scanner.next();
            channel.basicPublish(EXCHANGER_NAME,"",null,message.getBytes());
            System.out.println("生产者发送消息:"+message);
        }
    }
}

消费者 1:

package com.run.rabbitmq.five;

import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.run.rabbitmq.utils.RabbitMqUtils;

/**
 * @Date: 2021/07/07/9:45
 *
 * 消息接收
 */
public class ReceiveLogs01 {

    //交换机名称
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //声明一个临时队列
        /**
         * 生成一个临时队列、队列的名称是随机的
         * 当消费者断开与队列的连接的时候  队列就自动删除
         */
        String queueName = channel.queueDeclare().getQueue();
        /**
         * 绑定交换机与队列
         */
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        System.out.println("等待接收消息....把接受到的消息打印在终端");

        //接收消息
        DeliverCallback deliverCallback = (consumerTag,message) -> {
            System.out.println("消费机01 接收消息:"+new String(message.getBody()));
        };
        //消费者取消消息回调接口
        channel.basicConsume(queueName,true,deliverCallback,consumerTge ->{});
    }
}

消费者 2:

package com.run.rabbitmq.five;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.run.rabbitmq.utils.RabbitMqUtils;

/**
 * @Date: 2021/07/07/9:45
 *
 * 消息接收
 */
public class ReceiveLogs02 {

    //交换机名称
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //声明一个临时队列
        /**
         * 生成一个临时队列、队列的名称是随机的
         * 当消费者断开与队列的连接的时候  队列就自动删除
         */
        String queueName = channel.queueDeclare().getQueue();
        /**
         * 绑定交换机与队列
         */
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        System.out.println("等待接收消息....把接受到的消息打印在终端");

        //接收消息
        DeliverCallback deliverCallback = (consumerTag,message) -> {
            System.out.println("消费机02 接收消息:"+new String(message.getBody()));
        };
        //消费者取消消息回调接口
        channel.basicConsume(queueName,true,deliverCallback,consumerTge ->{});
    }
}

二、Direct exchange(直接交换机)

direct 这种类型的工作方式是,消息只去到它绑定的routingKey 队列中去。

代码:
生产者:

package com.run.rabbitmq.six;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.run.rabbitmq.utils.RabbitMqUtils;

import java.util.Scanner;

/**
 * @Date: 2021/07/07/10:29
 *
 * 直接交换机    生产者
 */
public class DirectLogs {
    //交换机的名称
    public static final String EXCHANGER_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.exchangeDeclare(EXCHANGER_NAME, BuiltinExchangeType.DIRECT);

        Scanner scanner = new Scanner(System.in);

        System.out.println("error   info    warning");

        while (scanner.hasNext()){
            String message = scanner.next();
            channel.basicPublish(EXCHANGER_NAME,message,null,message.getBytes());
            System.out.println("生产者发送消息:"+message);
        }
    }
}

消费者 1:

package com.run.rabbitmq.six;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.run.rabbitmq.utils.RabbitMqUtils;

/**
 * @Date: 2021/07/07/10:20
 *
 *  直接交换机   消费者
 */
public class ReceiveLogsDirect01 {

    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //声明一个队列
        channel.queueDeclare("console",false,false,false,null);
        //队列绑定交换机
        channel.queueBind("console",EXCHANGE_NAME,"info");
        channel.queueBind("console",EXCHANGE_NAME,"warning");
        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("ReceiveLogsDirect01 接收消息:"+new String(message.getBody()));
        };
        channel.basicConsume("console",true,deliverCallback, consumerTag -> {});
        System.out.println("等待接收消息....把接受到的消息打印在终端");
    }

}

消费者 2 :

package com.run.rabbitmq.six;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.run.rabbitmq.utils.RabbitMqUtils;

/**
 * @Date: 2021/07/07/10:20
 *
 *  直接交换机   生产者
 */
public class ReceiveLogsDirect02 {

    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //声明一个队列
        channel.queueDeclare("disk",false,false,false,null);
        //队列绑定交换机
        channel.queueBind("disk",EXCHANGE_NAME,"error");
        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("ReceiveLogsDirect02 接收消息:"+new String(message.getBody()));
        };
        channel.basicConsume("disk",true,deliverCallback, consumerTag -> {});
        System.out.println("等待接收消息....把接受到的消息打印在终端");
    }

}

三、Topics交换机(主题交换机)

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

在这个规则列表中,其中有两个替换符是大家需要注意的

*(星号)可以代替一个单词

#(井号)可以替代零个或多个单词

当队列绑定关系是下列这种情况时需要引起注意
当一个队列绑定键是#,那么这个队列将接收所有数据,就有点像 fanout 了
如果队列绑定键当中没有#和*出现,那么该队列绑定类型就是 direct 了

代码:
消费者 1 :

package com.run.rabbitmq.seven;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.run.rabbitmq.utils.RabbitMqUtils;

/**
 * @Date: 2021/07/07/10:49
 *
 *
 * 主题交换机 消费者 1
 */
public class ReceiveLogsTopic01 {
    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //声明一个队列
        String queueName = "Q1";
        channel.queueDeclare(queueName,false,false,false,null);
        //队列绑定交换机
        channel.queueBind(queueName,EXCHANGE_NAME,"*.orange.*");
        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("ReceiveLogsTopic01 接收消息:"+new String(message.getBody()));
        };
        channel.basicConsume(queueName,true,deliverCallback, consumerTag -> {});
        System.out.println("等待接收消息....把接受到的消息打印在终端");
    }
}

消费者 2 :

package com.run.rabbitmq.seven;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.run.rabbitmq.utils.RabbitMqUtils;

/**
 * @Date: 2021/07/07/10:49
 *
 * 主题交换机 消费者 2
 */
public class ReceiveLogsTopic02 {
    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //声明一个队列
        String queueName = "Q2";
        channel.queueDeclare(queueName,false,false,false,null);
        //队列绑定交换机
        channel.queueBind(queueName,EXCHANGE_NAME,"*.*.rabbit");
        channel.queueBind(queueName,EXCHANGE_NAME,"lazy.#");
        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("ReceiveLogsTopic02 接收消息:"+new String(message.getBody()));
        };
        channel.basicConsume(queueName,true,deliverCallback, consumerTag -> {});
        System.out.println("等待接收消息....把接受到的消息打印在终端");
    }
}

生产者 :

package com.run.rabbitmq.seven;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.run.rabbitmq.utils.RabbitMqUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * @Date: 2021/07/07/10:49
 *
 * 主题交换机 生产者
 */
public class TopicLogs {
    //交换机的名称
    public static final String EXCHANGER_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.exchangeDeclare(EXCHANGER_NAME, BuiltinExchangeType.TOPIC);

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

        for (Map.Entry<String, String> stringStringEntry : bindingKeyMap.entrySet()) {
            String routingKey = stringStringEntry.getKey();
            String message = stringStringEntry.getValue();
            channel.basicPublish(EXCHANGER_NAME,routingKey,null,message.getBytes("UTF-8"));
            System.out.println("生产者发出消息:"+message);
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值