RabbitMQ的工作模式之三发布/订阅(Publish/Subscribe)模式

RabbitMQ的工作模式之三发布/订阅(Publish/Subscribe)模式

一个生产者,多个消费者,每个消费者获取的信息完全相同,发布订阅模式下,生产者和交换机打交道,由交换机将信息发送给对应绑定的队列

导入依赖



  com.rabbitmq
  amqp-client
  5.7.3

首先创建工具类,用以生成连接,避免重复书写此段代码

public class RabbitMQUtil {
    private static ConnectionFactory factory = new ConnectionFactory();
    static{
        //用户名
        factory.setUsername("hello");
        //密码
        factory.setPassword("123456");
        //虚拟机
        factory.setVirtualHost("/myhost");
        //IP地址,运行rabbitmq组件的主机ip地址
        factory.setHost("192.168.31.14");
        //端口
        factory.setPort(5672);
    }

    public static Connection getConnection(){
        Connection connection = null;
        try {
            connection = factory.newConnection();
            return  connection;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return null;
    }
}

生产者

public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //获取连接
        Connection connection = RabbitMQUtil.getConnection();
        //创建通道
        Channel channel = connection.createChannel();
        /**
         * 声明交换机
         * 参数1:交换机名称
         * 参数2:交换机类型:fanout、direct、topic、headers
         */
        channel.exchangeDeclare("pubsub_exchange", BuiltinExchangeType.FANOUT);
        //在发布订阅模式下,生产者不再和队列打交道,而是直接将消息发送到交换机
        //参数1:是交换机的名称
        //参数2:是路由key,暂时不用
        //参数3:是额外的参数
        //参数4:要发布的消息
        channel.basicPublish("pubsub_exchange","",null,"发送信息".getBytes());
        channel.close();
        connection.close();
    }
}

消费者

public class Customer1{

    public static void main(String[] args) throws IOException {
        //获取连接
        Connection connection = RabbitMQUtil.getConnection();
        //创建通道
        final Channel channel = connection.createChannel();
        //声明队列
        channel.queueDeclare("qn_queue",false,false,false,null);
        //将对列与交换机进行绑定
        //参数3是 路由key
        channel.queueBind("qn_queue","pubsub_exchange","");
        //消费
        channel.basicConsume("qn_queue",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("customer1收到消息:"+new String(body));
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}
public class Customer2{
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMQUtil.getConnection();
        final Channel channel = connection.createChannel();
        //声明一个对列
        channel.queueDeclare("xc_queue",false,false,false,null);
        //将队列与交换机进行绑定
        //参数1:队列的名称
        //参数2:交换机的名称
        //参数3:是路由key ,暂时不用
        channel.queueBind("xc_queue","pubsub_exchange","");
        //签收消息:false表示手动编程的方式签收
        channel.basicConsume("xc_queue",false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("customer2接收的消息:"+new String(body));
                //签收
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }
}

注:生产者发送消息至交换机,交换机按照key分配给相应队列,这里测试时若先运行消费者端需要确保交换机被创建,故需要在消费者端声明交换机,此时生产者端不需要声明交换机,当然,如果先运行生产者端,则需要在生产者端先声明交换机,此时消费者端可以不用声明交换机,总之躯体情况具体分析,灵活运用,当然为了省事,可以一律声明。

你可能感兴趣的:(rabbitmq,队列,java,交换机)