rabbitmq学习笔记5 : 发布订阅模式 Publish/Subscribe

一、概念和模型

  • 发布订阅模式,同一条信息发送给多个消费者。该模式是通过加入路由得以实现的,消息生产者将信息发送到管道,管道将消息发送给与之绑定的队列,然后消费者从相应的队列中获取消息并进行处理。场景可用于微信公众号等功能。

      

  

二、Java代码实现

  • 创建MQ连接工具类
public class RabbitmqUntil {
    //获取连接
    public static Connection getRabbitmqConnection() throws Exception{
        //定义连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //设置服务地址
        factory.setHost("127.0.0.1");
        //设置端口(这里的端口号指定是AMQP协议所用的端口号)
        factory.setPort(5672);
        //设置数据库
        factory.setVirtualHost("/test");
        //设置用户名
        factory.setUsername("test");
        //设置密码
        factory.setPassword("test");
        return factory.newConnection();
    }
}
  • 创建消息生产者
public class PublishSender {
    //路由名称
    public static final String ROUNTING_NAME="publish rounting";

    public static void sendMessage()throws Exception{
        //1、获取连接
        Connection rabbitmqConnection = RabbitmqUntil.getRabbitmqConnection();
        //2、创建通道
        Channel channel = rabbitmqConnection.createChannel();

        //3、创建路由(参数1:路由名称;参数2:模式名称,fanout表示发布订阅模式)
        channel.exchangeDeclare(ROUNTING_NAME,"fanout");

        //4、设置每次发送信息不超过1条
        channel.basicQos(1);

        String message="hello ,I am Publish/Subscribe";

        //5、发布消息
        channel.basicPublish(ROUNTING_NAME,"",null,message.getBytes());
    }

    public static void main(String[] args)throws Exception {
        PublishSender.sendMessage();
    }
}

注:创建路由时channel.exchangeDeclare(ROUNTING_NAME,"fanout");第二个参数必须是“fanout”,表示该模式为发布订阅模式

  • 消费者一
public class publishReceiver1 {

    //路由名称名称
    public static final String ROUNTING_NAME="publish rounting";
    //队列名称
    public static final String PUBLISH_ROUNTING_QUEQU="publish rounting queue1";

    public static void receiveMessage() throws Exception{
        //1、创建连接
        Connection rabbitmqConnection = RabbitmqUntil.getRabbitmqConnection();
        //2、获取通道
        final Channel channel = rabbitmqConnection.createChannel();
        //3、定义队列
        channel.queueDeclare(PUBLISH_ROUNTING_QUEQU,true,false,false,null);
        //4、设置每次处理信息不超过1条
        channel.basicQos(1);
        //5、将路由和队列进行绑定
        channel.queueBind(PUBLISH_ROUNTING_QUEQU,ROUNTING_NAME,"");
        //6、定义消费用户
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                try{
                    System.out.println("消费者1:"+new String(body,"utf-8"));
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            }
        };
        //7、监听队列消息
        channel.basicConsume(PUBLISH_ROUNTING_QUEQU,false,defaultConsumer);
    }

    public static void main(String[] args)throws Exception {
        publishReceiver1.receiveMessage();
    }
}
  • 消费者二
public class publishReceiver2 {

    //路由名称名称
    public static final String ROUNTING_NAME="publish rounting";
    //队列名称
    public static final String PUBLISH_ROUNTING_QUEQU="publish rounting queue2";

    public static void receiveMessage() throws Exception{
        //1、创建连接
        Connection rabbitmqConnection = RabbitmqUntil.getRabbitmqConnection();
        //2、获取通道
        final Channel channel = rabbitmqConnection.createChannel();
        //3、定义队列
        channel.queueDeclare(PUBLISH_ROUNTING_QUEQU,true,false,false,null);
        //4、设置每次处理信息不超过1条
        channel.basicQos(1);
        //5、将路由和队列进行绑定
        channel.queueBind(PUBLISH_ROUNTING_QUEQU,ROUNTING_NAME,"");
        //6、定义消费用户
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                try{
                    System.out.println("消费者2:"+new String(body,"utf-8"));
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    channel.basicAck(envelope.getDeliveryTag(),false);
                }
            }
        };
        //7、监听队列消息
        channel.basicConsume(PUBLISH_ROUNTING_QUEQU,false,defaultConsumer);
    }

    public static void main(String[] args)throws Exception {
        publishReceiver2.receiveMessage();
    }
}

注:第5步将路由器与队列进行绑定,这样消费者就可以丛对应的队列中获取到信息

  • 运行三个类的main方法后,可以看到消费者都可以接受到消息,并且在rabbitmq控制台可以看到路由器与队列的关系

 

注:路由器没有存储功能,所以在没有与之绑定的队列之前,执行发送消息,数据会丢失。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值