RabbitMq学习(5) 指定RouteKey的Direct模型

一、Direct模型

Direct模型又称订阅/路由发布模型,根据不同的路由规则,不同的消费者通过通道绑定一个到多个路由临时队列,而这些路由队列会监听从交换机发送过来的,指定路由的消息。实现通过路由使区别的广播给不同的消费者。
如下图所示,通过不同的路由设置,消费者1,2,3都会消费来着route_1的消息,消费者2,3会收到来着route_2的消息,消费者3会收到来着route_3的消息
在这里插入图片描述

代码实现关键

1. 生产者
 //绑定交换机以及申明交换机类型
channel.exchangeDeclare("log_direct", "direct");

通过通道绑定交换机和声明交换机类型, 该交换机不存在时会自动生成。

//通过通道向交换机发送消息,指定交换机, 路由(String), 其他参数,消息本体
channel.basicPublish("log_direct", Route.DIRECT_INFO, null, "Info msg".getBytes());
2. 消费者
//绑定交换机,声明交换机类型
channel.exchangeDeclare("log_direct", "direct");
//生成临时队列并获得名称
String queue = channel.queueDeclare().getQueue();
//绑定队列交换机,声明路由
channel.queueBind(queue,"log_direct",Route.DIRECT_INFO,null);

与生产者一样,先绑定交换机。之后,使用临时队列获取交换机中的消息。

queueBind() 方法通过声明队列,交换机和路由来确定该通道传输怎样路由规则的消息。可以多次使用queueBind()方法绑定不同的路由规则。

三、代码实现

模拟日志系统, 生产者将发送三种消息:info warning error, 然后通过direct交换机广播给三种消费者。InfoCustomer、WarningCustomer、ErrorCustemor。其中Info只能接受info消息,Warning能接受info、warning消息,Error能接受info、warning、error消息。

1.静态路由提供类
public class Route {
    public static final String DIRECT_INFO = "info";
    public static final String DIRECT_WARNING = "warning";
    public static final String DIRECT_ERROR = "error";
}
2.生产者
public class Provider extends Thread{
    
    @Override
    public void run() {
        Connection connection = null;
        Channel channel = null;

        try {
            connection = RabbitMqUtil.getConnection();
            channel = connection.createChannel();
            //绑定交换机, 指定交换机类型
            channel.exchangeDeclare("log_direct", "direct");

            //发送三条路由为"info" "warning" "error" 的消息到交换器机
            channel.basicPublish("log_direct", Route.DIRECT_INFO, null, "Info msg".getBytes());
            channel.basicPublish("log_direct", Route.DIRECT_WARNING, null, "Warning msg".getBytes());
            channel.basicPublish("log_direct", Route.DIRECT_ERROR, null, "Error msg".getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            RabbitMqUtil.closeChannelAndConnection(channel,connection);
        }
    }
}
3.InfoCustomer
public class InfoCustomer extends Thread{

    @Override
    public void run() {
        Connection connection = null;
        Channel channel = null;

        try {
            connection = RabbitMqUtil.getConnection();
            channel = connection.createChannel();

            //声明交换机与交换机类型
            channel.exchangeDeclare("log_direct", "direct");

            //生成临时队列并获得名称
            String queue = channel.queueDeclare().getQueue();

            //绑定队列交换机,声明路由
            channel.queueBind(queue,"log_direct",Route.DIRECT_INFO,null);

            channel.basicConsume(queue,true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("InfoCustomer 消费了 " + new String(body));
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
4.WarningCustomer
public class WarningCustomer extends Thread {
    @Override
    public void run() {
        Connection connection = null;
        Channel channel = null;

        try {
            connection = RabbitMqUtil.getConnection();
            channel = connection.createChannel();

            //声明交换机与交换机类型
            channel.exchangeDeclare("log_direct", "direct");

            //生成临时队列并获得名称
            String queue = channel.queueDeclare().getQueue();

            //绑定队列交换机,声明路由
            channel.queueBind(queue,"log_direct",Route.DIRECT_INFO,null);
            channel.queueBind(queue,"log_direct",Route.DIRECT_WARNING,null);

            channel.basicConsume(queue,true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("WarningCustomer 消费了 " + new String(body));
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
5.ErrorCustomer
public class ErrorCustomer extends Thread{
    @Override
    public void run() {
        Connection connection = null;
        Channel channel = null;

        try {
            connection = RabbitMqUtil.getConnection();
            channel = connection.createChannel();

            //声明交换机与交换机类型
            channel.exchangeDeclare("log_direct", "direct");

            //生成临时队列并获得名称
            String queue = channel.queueDeclare().getQueue();

            //绑定队列交换机,声明路由
            channel.queueBind(queue,"log_direct",Route.DIRECT_INFO,null);
            channel.queueBind(queue,"log_direct",Route.DIRECT_WARNING,null);
            channel.queueBind(queue,"log_direct",Route.DIRECT_ERROR,null);

            channel.basicConsume(queue,true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("ErrorCustomer 消费了 " + new String(body));
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
6.启动方法
public static void main(String[] args) throws InterruptedException {

        //仍然需要注意, 消费者因先于生产者被创建
        Thread err = new ErrorCustomer();
        Thread war = new WarningCustomer();
        Thread inf = new InfoCustomer();
        err.start();
        war.start();
        inf.start();

        Thread.sleep(1000);

        Thread pro = new Provider();
        pro.start();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值