Skip to content

rabbitMQ基本使用 ​

一、依赖 ​

xml
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.12.0</version>
</dependency>

二、常量类 ​

java
package com.lcy.cloud.video.constant;

public class RabbitmqConstant {
    /**
     * 主机--ip
     */
    public static final String HOST = "121.40.98.21";

    /**
     * 端口
     */
    public static final int PORT = 5672;

    /**
     * 用户名
     */
    public static final String USERNAME = "guest";

    /**
     * 密码
     */
    public static final String PASSWORD = "guest";

    /**
     * 虚拟主机
     */
    public static final String VIRTUAL_HOST = "/dev";

    /**
     * 队列名称
     */
    public static final String QUEUE_NAME = "test";

    /**
     * 广播交换机名称
     */
    public static final String PUB_EXCHANGE_NAME = "pub_exchange";

    /**
     * 点对点交换机名称
     */
    public static final String DIRECT_EXCHANGE_NAME = "direct_exchange";

    /**
     * topic交换机名称
     */
    public static final String TOPIC_EXCHANGE_NAME = "topic_exchange";
}

三、公共方法类 ​

java
package com.lcy.cloud.common.util;

import com.lcy.cloud.common.constant.RabbitmqConstant;
import com.rabbitmq.client.ConnectionFactory;

public class RabbitmqUtil {
    /**
     * 获取rabbitmq连接工厂类
     **/
    public static ConnectionFactory getConnectionFactory() {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(RabbitmqConstant.HOST);
        connectionFactory.setPort(RabbitmqConstant.PORT);
        connectionFactory.setUsername(RabbitmqConstant.USERNAME);
        connectionFactory.setPassword(RabbitmqConstant.PASSWORD);
        connectionFactory.setVirtualHost(RabbitmqConstant.VIRTUAL_HOST);
        return connectionFactory;
    }
}

四、普通消息--点对点交换机(默认) ​

五、生产者 ​

java
package com.lcy.cloud.video.product;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.common.constant.RabbitmqConstant;
import com.lcy.cloud.common.util.RabbitmqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class NormalRabbitMqProduct {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        try (Connection connection = connectionFactory.newConnection();
                Channel channel = connection.createChannel()) {
            /*
             * 队列名称
             * 持久化配置:mq重启后还在
             * 是否独占:只能有一个消费者监听队列;当connection关闭是否删除队列,一般是false,发布订阅是独占
             * 自动删除: 当没有消费者的时候,自动删除掉,一般是false
             * 其他参数:队列不存在则会自动创建,如果存在则不会覆盖,所以此时的时候需要注意属性
             */
            channel.queueDeclare(RabbitmqConstant.QUEUE_NAME, false, false, false, null);
            String message = "message";
            channel.basicPublish("", RabbitmqConstant.QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}

六、消费者 ​

两种方式进行消费。

如果要使消费者一直监听消息,把获取连接自动关闭的方法提取到外面。

如果是多个消费者消费消息,默认是轮训的分配消费,如1-10条消息,1、3、5、7、9分配在了消费者1上其它的在消费者2上,当消费者1处理很缓慢(服务器资源)的时候,这个时候就会造成消息堆积。

通过设置 channel.basicQos(1); ,每次只拿一条消息进行消费

java
package com.lcy.cloud.video.consumer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.common.constant.RabbitmqConstant;
import com.lcy.cloud.common.util.RabbitmqUtil;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
import com.rabbitmq.client.Envelope;

public class NormalRabbitMqConsumer {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        try (Connection connection = connectionFactory.newConnection();
                Channel channel = connection.createChannel()) {
            //每次只拿一条消息进行消费
            channel.basicQos(1);
            /*
             * 队列名称
             * 持久化配置:mq重启后还在
             * 是否独占:只能有一个消费者监听队列;当connection关闭是否删除队列,一般是false,发布订阅是独占
             * 自动删除: 当没有消费者的时候,自动删除掉,一般是false
             * 其他参数:队列不存在则会自动创建,如果存在则不会覆盖,所以此时的时候需要注意属性
             */
            channel.queueDeclare(RabbitmqConstant.QUEUE_NAME, false, false, false, null);
            //Consumer consumer = new DefaultConsumer(channel){
            //    @Override
            //    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
            //        // consumerTag 是固定的 可以做此会话的名字, deliveryTag 每次接收消息+1
            //        System.out.println("consumerTag消息标识="+consumerTag);
            //        //可以获取交换机,路由健等
            //        System.out.println("envelope元数据="+envelope);
            //        System.out.println("properties配置信息="+properties);
            //        System.out.println("body="+new String(body,StandardCharsets.UTF_8));
            //    }
            //};
            ////自动确认消息,但是生产环境是友好的,最好在处理完消息以后手动确认
            //channel.basicConsume(RabbitmqConstant.QUEUE_NAME,false,consumer);
            DeliverCallback deliverCallback = (consumerTag, message) -> {
                String body = new String(message.getBody(), StandardCharsets.UTF_8);
                System.out.println(" [x] Received '" + body + "'");
            };
            channel.basicConsume(RabbitmqConstant.QUEUE_NAME, true, deliverCallback, consumerTag -> {});
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}

七、广播模式(发布订阅模式) ​

发布-订阅模型中,消息生产者不再是直接面对queue(队列名称),而是直面exchange,都需要经过exchange来进行消息的发送, 所有发往同一个fanout交换机的消息都会被所有监听这个交换机的消费者接收到。 发布订阅-消息模型引入fanout交换机。

  • 通过把消息发送给交换机,交互机转发给对应绑定的队列

  • 交换机绑定的队列是排它独占队列,自动删除

八、生产者 ​

java
package com.lcy.cloud.video.product;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class PubRabbitMqProduct {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        try (Connection connection = connectionFactory.newConnection();
                Channel channel = connection.createChannel()) {
            String message = "pub message";
            //绑定交换机,fanout扇形,即广播类型
            channel.exchangeDeclare(RabbitmqConstant.PUB_EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
            //发送消息
            channel.basicPublish(RabbitmqConstant.PUB_EXCHANGE_NAME, "", null, message.getBytes(StandardCharsets.UTF_8));
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}

九、消费者 ​

java
package com.lcy.cloud.video.consumer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class PubRabbitMqConsumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

        //绑定交换机,fanout扇形,即广播类型
        channel.exchangeDeclare(RabbitmqConstant.PUB_EXCHANGE_NAME, BuiltinExchangeType.FANOUT);
        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();
        //绑定队列和交换机,fanout交换机不用指定routingkey
        channel.queueBind(queueName, RabbitmqConstant.PUB_EXCHANGE_NAME, "");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
    }
}

十、路由模式 ​

交换机类型是Direct,队列和交换机绑定,需要指定一个路由key( 也叫Bingding Key),消息生产者发送消息给交换机,需要指定routingKey,交换机根据消息的路由key, 转发给对应的队列

十一、生产者 ​

java
package com.lcy.cloud.video.product;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class RouteRabbitMqProduct {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        try (Connection connection = connectionFactory.newConnection();
                Channel channel = connection.createChannel()) {
            //绑定交换机
            channel.exchangeDeclare(RabbitmqConstant.DIRECT_EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
            String error = "error message";
            String info = "info message";
            String debug = "debug message";

            //发送消息
            channel.basicPublish(RabbitmqConstant.DIRECT_EXCHANGE_NAME, "errorKey", null, error.getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(RabbitmqConstant.DIRECT_EXCHANGE_NAME, "infoKey", null, info.getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(RabbitmqConstant.DIRECT_EXCHANGE_NAME, "debugKey", null, debug.getBytes(StandardCharsets.UTF_8));
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}

十二、消费者 ​

java
package com.lcy.cloud.video.consumer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class RouteCommonRabbitMqConsumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

        //绑定交换机
        channel.exchangeDeclare(RabbitmqConstant.DIRECT_EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();
        //绑定队列和交换机
        channel.queueBind(queueName, RabbitmqConstant.DIRECT_EXCHANGE_NAME, "errorKey");
        channel.queueBind(queueName, RabbitmqConstant.DIRECT_EXCHANGE_NAME, "infoKey");
        channel.queueBind(queueName, RabbitmqConstant.DIRECT_EXCHANGE_NAME, "debugKey");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
    }
}
java
package com.lcy.cloud.video.consumer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class RouteErrorRabbitMqConsumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

        //绑定交换机
        channel.exchangeDeclare(RabbitmqConstant.DIRECT_EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();
        //绑定队列和交换机
        channel.queueBind(queueName, RabbitmqConstant.DIRECT_EXCHANGE_NAME, "errorKey");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
    }
}

十三、主题模式topic ​

交换机是 topic, 可以实现发布订阅模式fanout和路由模式Direct 的功能,更加灵活,支持模式匹配,通配符等

交换机同过通配符进行转发到对应的队列,* 代表一个词,#代表1个或多个词,一般用#作为通配符居多,比如 #.order, 会匹配 info.order 、sys.error.order, 而 *.order , 只会匹配 info.order, 之间是使用. 点进行分割多个词的; 如果是 ., 则info.order、error.order都会匹配

注意:

  • 交换机和队列绑定时用的binding使用通配符的路由健

  • 生产者发送消息时需要使用具体的路由健

十四、生产者 ​

java
package com.lcy.cloud.video.product;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class TopicRabbitMqProduct {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        try (Connection connection = connectionFactory.newConnection();
                Channel channel = connection.createChannel()) {
            //绑定交换机
            channel.exchangeDeclare(RabbitmqConstant.TOPIC_EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
            String error = "error message";
            String info = "info message";
            String debug = "debug message";

            //发送消息
            channel.basicPublish(RabbitmqConstant.TOPIC_EXCHANGE_NAME, "error.key", null, error.getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(RabbitmqConstant.TOPIC_EXCHANGE_NAME, "info.key", null, info.getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(RabbitmqConstant.TOPIC_EXCHANGE_NAME, "debug.key", null, debug.getBytes(StandardCharsets.UTF_8));
        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}

十五、消费者 ​

java
package com.lcy.cloud.video.consumer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class TopicCommonRabbitMqConsumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

        //绑定交换机
        channel.exchangeDeclare(RabbitmqConstant.TOPIC_EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();
        //绑定队列和交换机
        channel.queueBind(queueName, RabbitmqConstant.TOPIC_EXCHANGE_NAME, "*.key");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
    }
}
java
package com.lcy.cloud.video.consumer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

import com.lcy.cloud.video.constant.RabbitmqConstant;
import com.lcy.cloud.video.util.RabbitmqUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class TopicErrorRabbitMqConsumer {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = RabbitmqUtil.getConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();

        //绑定交换机
        channel.exchangeDeclare(RabbitmqConstant.TOPIC_EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //获取队列(排它队列)
        String queueName = channel.queueDeclare().getQueue();
        //绑定队列和交换机
        channel.queueBind(queueName, RabbitmqConstant.TOPIC_EXCHANGE_NAME, "error.key");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
    }
}