【RabbitMQ】初识MQ消息队列

一、安装以及启动

  1. 安装(mac):brew install rabbitmq 各个版本rabbitmq下载
  2. 启动方式1:
    (1)进入目录下:cd /usr/local/Cellar/rabbitmq/3.6.6
    (2)执行:sbin/rabbitmq-server
  3. 启动方式2*:
    (1)终端执行:vi ~/.bashrc vi ~/.zshrc
    (2)添加环境变量:export PATH=$PATH:/usr/local/sbin
    (3)启动mq:rabbitmq-server
  4. 客户端:http://localhost:15672(初始用户密码都是guest),显示如下界面安装启动成功:
    在这里插入图片描述

二、第1种模型:hello world

最简单一对一关系的消费者生产者模型

1、管理页面加入新的用户和消费队列的虚拟机
添加用户:
在这里插入图片描述添加虚拟主机:
在这里插入图片描述

2、创建java项目,引入依赖

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

3、发送消息到队列

/**
     * 生产者
     */
    @Test
    public void produce() throws IOException, TimeoutException {
        // mq连接服务器工厂对象
        ConnectionFactory factory = new ConnectionFactory();
        // 设置连接主机
        factory.setHost( "127.0.0.1" );
        // 设置端口
        factory.setPort( 5672 );
        // 设置连接虚拟主机
        factory.setVirtualHost( "/ems" );
        // 设置用户名密码
        factory.setUsername( "ems" );
        factory.setPassword( "ems" );

        // 获取连接对象
        Connection connection = factory.newConnection();

        // 获取连接通道对象
        Channel channel = connection.createChannel();

        // 通道绑定对应的消息队列
        // 参数1:队列名称  存在连接 不存在则创建
        // 参数2:队列属否需要持久化  不持久化重启队列则会被删除
        // 参数3:是否独占队列  true:只可当前通道访问  fasle:不独占队列
        // 参数4:是否在消费完成后删除队列
        // 参数5:额外参数
        channel.queueDeclare("hello", false, false, false, null);

        // 发布消息
        // 参数1:交换机
        // 参数2:发送队列
        // 参数3:发布消息的属性
        // 参数4:发布消息的内容
        channel.basicPublish( "", "hello", null, "hello world11".getBytes() );

        channel.close();
        connection.close();
    }

发送成功在管理界面的Queues标签页下会看到如下:
在这里插入图片描述
4、消费者

/**
     * 一直监听消息队列的消息  发一条消息取一次
     * @param args
     * @throws IOException
     * @throws TimeoutException
     */
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost( "127.0.0.1" );
        factory.setPort( 5672 );
        // 虚拟主机
        factory.setVirtualHost( "/ems" );
        factory.setUsername( "ems" );
        factory.setPassword( "ems" );

        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        // 绑定消息队列
        channel.queueDeclare( "hello", false, false, false, null );

        // 消费消息
        // 参数1:消费那个队列的消息
        // 参数2:开启消息的自动确认机制
        // 参数3:消费消息的回掉接口
        channel.basicConsume( "hello", true, new DefaultConsumer( channel ) {
            /**
             *
             * @param consumerTag 标签
             * @param envelope
             * @param properties
             * @param body 接收的消息队列的内容
             * @throws IOException
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // 打印消息队列取出的内容
                System.out.println(consumerTag + ":" + new String( body ));
            }
        } );
    }

读取成功,获取到生产者发送的消息:
在这里插入图片描述
5、连接工具类

public class MqUtils {
    private static ConnectionFactory connectionFactory;
    static {
        connectionFactory = new ConnectionFactory();
        connectionFactory.setHost( "127.0.0.1" );
        connectionFactory.setPort( 5672 );
        connectionFactory.setVirtualHost( "/ems" );
        connectionFactory.setUsername( "ems" );
        connectionFactory.setPassword( "ems" );
    }
    /**
     * 获取mq连接
     * @return
     */
    public static Connection getConnection() {
        try {
            return connectionFactory.newConnection();
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 关闭通道和连接
     * @param channel
     * @param connection
     */
    public static void closeChannelAndConnection(Channel channel, Connection connection){
        try {
            if(channel != null) channel.close();
            if(connection != null) connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

6、API参数

三、第2种模型:平均消息模型

消费者1消费奇数,消费者2消费偶数
在这里插入图片描述

  1. 生产者:
public void sendMessage() throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare( "work", true, false, false, null );
        for (int i = 0; i < 10; i++) {
            channel.basicPublish( "", "work", MessageProperties.PERSISTENT_TEXT_PLAIN, (i + "work work").getBytes() );
        }
        MqUtils.closeChannelAndConnection( channel, connection );
    }
  1. 消费者1:
/**
     * 消费者1 消费13579....
     * 消费者2 消费02468....
     *
     */
    public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare( "work", true, false, false, null );
        channel.basicConsume( "work", true, new DefaultConsumer( channel ) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:"+new String( body ));
            }
        });
    }
  1. 消费者2:
public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare( "work", true, false, false, null );
        channel.basicConsume( "work", true, new DefaultConsumer( channel ) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者2:"+new String( body ));
            }
        });
    }
附加:消息确认机制 – 手动消息确认
public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        // 一次消费一条消息 ********增加的********
        channel.basicQos( 1 );
        channel.queueDeclare( "work", true, false, false, null );
        // ********增加的******** channel.basicConsume( "work", 是否自动确认。。。。。。。。
        channel.basicConsume( "work", false, new DefaultConsumer( channel ) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:"+new String( body ));
                // ********增加的********
                // 手动确认 参数1:手动确认参数标示  参数2:是否开启多条消息确认
                channel.basicAck( envelope.getDeliveryTag(), false );
            }
        });
    }

四、第3种模型:广播消息模型

在这里插入图片描述

  1. 生产者
@SpringBootTest
public class ProduceTest {
    @Test
    public void sendMsg() throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        // 1.声明交换机  exchangeDeclare("交换机名称", "交换机类型");
        channel.exchangeDeclare("logs", "fanout");
        // 2.向交换机发送消息 basicPublish(交换机,路由key,。。 )
        channel.basicPublish( "logs", "", null, "这是交换机中的消息".getBytes() );
        MqUtils.closeChannelAndConnection( channel, connection );
    }

}
  1. 消费者(可以有多个 代码一样)
@SpringBootTest
public class CustomerTest01 {
    public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        // 1.声明一个交换机
        channel.exchangeDeclare( "logs", "fanout" );
        // 2.创建临时队列(消费队列都是临时的,减轻mq的负担)
        String queue = channel.queueDeclare().getQueue();
        // 3.绑定临时队列和交换机  queueBind( 队列, "交换机", "路由key" );
        channel.queueBind( queue, "logs", "" );
        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(new String( body ));
            }
        });
    }
}

五、第4种模型:路由消息模型

该模型是基于广播模型的更加高级的用法,生产者生产消息会绑定一个路由key,交换机会发送消息给绑定同一路由的消费者
在这里插入图片描述

  1. 生产者:
@Test
    public void sendMsg() throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        // 如果指定fanout(广播)路由是不生效的
        // 指定路由模式
        channel.exchangeDeclare( "logs_direct", "direct" );
        // 绑定路由key,每条消息会被绑定同一路由的消费者接收
        String routerKey = "router_key_error";
        for (int i = 0; i < 10; i++) {
            channel.basicPublish( "logs_direct", routerKey, null, ("这是路由发的消息  key:"+routerKey+"  i:"+i).getBytes() );
        }
        MqUtils.closeChannelAndConnection( channel, connection );
    }
  1. 消费者1:
public class CustomerTest01 {
    public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        // 声明路由模式的交换机
        channel.exchangeDeclare( "logs_direct", "direct" );
        String queue = channel.queueDeclare().getQueue();
        // 路由key
        String routerKey = "router_key_error";
        // 绑定交换机和路由key
        channel.queueBind( queue, "logs_direct", routerKey );
        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("消费者1:" + new String( body ));
            }
        } );
    }
}
  1. 消费者2:
public class CustomerTest02 {
    static String routerKey = "router_key_error";
    public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare( "logs_direct", "direct" );
        String queue = channel.queueDeclare().getQueue();
        channel.queueBind( queue, "logs_direct", routerKey );
        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("消费者2:" + new String( body ));
            }
        } );
    }
}

六、第5种模型:topic消息模型

*(星)可以代替一个词。
#(hash)可以代替零个或多个单词。

  1. 生产者
static String EXCHANGE_NAME = "topics";

    @Test
    public void sendMsg() throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        // topic模式  可以 '通配符' 模糊匹配
        // auth.# 匹配多个  比如 auth.irs.compose 和 auth.irs都可以匹配
        // auth.* 匹配单个 只能匹配auth.irs
        channel.exchangeDeclare( EXCHANGE_NAME, "topic" );
        // topic的路由key
        String routerKey = "user.save";
        for (int i = 0; i < 10; i++) {
            channel.basicPublish( EXCHANGE_NAME, routerKey, null, ("这是路由发的消息  key:"+routerKey+"  i:"+i).getBytes() );
        }
        MqUtils.closeChannelAndConnection( channel, connection );
    }
  1. 消费者1
	public class CustomerTest01 {
    static String EXCHANGE_NAME = "topics";
    // 通配符 匹配一个单词
    static String ROUTER_KEY = "user.*";

    public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare( EXCHANGE_NAME, "topic" );
        String queue = channel.queueDeclare().getQueue();
        channel.queueBind( queue, EXCHANGE_NAME, ROUTER_KEY );
        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("消费者1:" + new String( body ));
            }
        } );
    }
}
  1. 消费者2
public class CustomerTest02 {
    static String EXCHANGE_NAME = "topics";
    // 所有user的
    static String ROUTER_KEY = "user.#";

    // 标示user前有一个单词,,user后面可以匹配多个单词
    // static String ROUTER_KEY = "*.user.#";

    public static void main(String[] args) throws IOException {
        Connection connection = MqUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare( EXCHANGE_NAME, "topic" );
        // 临时队列
        String queue = channel.queueDeclare().getQueue();
        channel.queueBind( queue, EXCHANGE_NAME, ROUTER_KEY );
        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("消费者2:" + new String( body ));
            }
        } );
    }
}

七、SpringBoot整合RabbitMQ

1、导入依赖
<dependency>
    	<groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、引入rabbitmq模版引擎
	@Autowired
    private RabbitTemplate rabbitTemplate;
3、hello world模型

生产者:

// hello world模型 convertAndSend(队列,消息)
rabbitTemplate.convertAndSend( "hello_api", "hello world" );

消费者:

@Component
@RabbitListener( queuesToDeclare = @Queue(value = "hello_api", durable = "false", exclusive = "false", autoDelete = "true"))
public class CutsomerTest {

    @RabbitHandler
    public void receivel(String message){
        System.out.println("消息是:"+message);
    }
}
4、平均模型

消费者:

// 平均消息模型 convertAndSend(队列,消息)
rabbitTemplate.convertAndSend( "work_api", "work model" );

生产者:

	@RabbitListener( queuesToDeclare = @Queue(value = "work_api"))
    public void getMsg1(String message){
        System.out.println("消费1:"+message);
    }

    @RabbitListener( queuesToDeclare = @Queue(value = "work_api"))
    public void getMsg2(String message){
        System.out.println("消费2:"+message);
    }
5、广播模型

生产者:

// 广播消息模型 convertAndSend(交换机,路由key,消息)
rabbitTemplate.convertAndSend( "logs_api", "", "public模型");

生产者:

	@RabbitListener( bindings = {
            // 声明一个临时队列
            @QueueBinding(
                    value = @Queue, // 不指定名称标示创建临时队列
                    exchange = @Exchange(value = "logs_api", type = "fanout") // 绑定交换机
            )
    })
    public void getMsg1(String message){
        System.out.println("消费1:"+message);
    }

    @RabbitListener( bindings = {
            // 声明一个临时队列
            @QueueBinding(
                    value = @Queue, // 不指定名称标示创建临时队列
                    exchange = @Exchange(value = "logs_api", type = "fanout") // 绑定交换机
            )
    })
    public void getMsg2(String message){
        System.out.println("消费2:"+message);
    }
6、路由模型

生产者:

// 路由消息模型 同上
rabbitTemplate.convertAndSend( "logs_direct_api", "error", "路由发送的消息" );

消费者:

@RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "logs_direct_api",type = "direct"),
                    key = {"info","error"} // 绑定info、error两个key键
            )
    })
    public void getMsg_all(String message){
        System.out.println("info_error"+message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "logs_direct_api",type = "direct"),
                    key = {"error"}
            )
    })
    public void getMsg_error(String message){
        System.out.println("error"+message);
    }
7、topic模型

生产者:

rabbitTemplate.convertAndSend( "logs_topic_api", "user.save", "topic发送的消息" );

消费者:

	@RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "logs_topic_api",type = "topic"),
                    key = {"user.save","user.*"}
            )
    })
    public void getMsg_all(String message){
        System.out.println("\"user.save\",\"user.*\"  "+message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(value = "logs_topic_api",type = "topic"),
                    key = {"user.#.#"}
            )
    })
    public void getMsg_error(String message){
        System.out.println("user.#   "+message);
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼小鱼啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值