介绍:

        RabbitMQ提供了6中消息模型  但第6种其实是RPC(远程过程调用)并不是MQ (message queue 消息队列) 所以暂时咱还不研究 如果想去了解RPC的话可以去学习一下dubbo 它就是一个轻量级的开源 RPC框架,今天咱们学习第一种 RrabbitMQ消息模型——基本消息模型

        如图所示 基本消息模型就是生产者------->消息队列------>消费者,消息生产者对应一个消息消费者:

springboot rabbitMQ 消息对象_消息队列

  搭建示例工程:

项目目录结构:

springboot rabbitMQ 消息对象_rabbitmq_02

1、创建springboot项目导入依赖:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2、创建工具类ConnectionUtil 因为消息生产者和消息消费都需要获取连接对象,所以在这里我们将获取连接的代码进行封装

package com.rabbitmq.utils;

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @author: shenwang
 * Date: 2021/7/3
 */
public class ConnectionUtil {
    public static Connection getConnection(){
        Connection connection=null;
        //创建连接工厂对象
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置RabbitMQ服务主机地址,默认localhost
        connectionFactory.setHost("localhost");
        //设置rabbitmq服务端口,默认5672
        connectionFactory.setPort(5672);

        //设置虚拟机名字,默认/
        connectionFactory.setVirtualHost("/");
        //设置用户连接名 默认guest
        connectionFactory.setUsername("ahua");
        //设置连接密码 默认guest
        connectionFactory.setPassword("123");

        try {
            //创建连接
            connection= connectionFactory.newConnection();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

3、消息生产者:

package com.rabbitmq.simple;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.utils.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 消息生产者
 * @author: shenwang
 * Date: 2021/7/2
 */
public class Producer {

    public static void main(String[] args) {
        try {
            //创建连接对象
            Connection connection = ConnectionUtil.getConnection();
            //创建频道
            Channel channel = connection.createChannel();
            /**
             * 声明式队列
             * 参数1:列队名称
             * 参数2:是否定义持久化队列
             * 参数3:是否独占本次连接
             * 参数4:是否在不使用的时候自动删除队列
             * 参数5:队列其他参数
             */
            channel.queueDeclare("simple_queue",true,false,false,null);
            //创建消息
            String message="hello world! my name is ahua";
            /**
             * 发送消息
             * 参数1:交换机名称,如果没有指定则使用默认 default Exchange
             * 参数2:路由key,简单模式可以传递队列名称
             * 参数3:消息其他属性
             * 参数4:消息内容
             */
            channel.basicPublish("","simple_queue",null,message.getBytes());
            //关闭资源
            channel.close();
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

}

启动咱们的消息生产者类可以在咱们的RabbitMQ Management中看到消息:

springboot rabbitMQ 消息对象_rabbitmq_03

4、消息消费者

package com.rabbitmq.simple;

import com.rabbitmq.client.*;
import com.rabbitmq.utils.ConnectionUtil;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 消息消费者
 * @author: shenwang
 * Date: 2021/7/3
 */
public class Consumer {
    public static void main(String[] args) {

        try {
            //创建连接
            Connection connection = ConnectionUtil.getConnection();
            //创建频道
            Channel channel = connection.createChannel();
            /**
             * 声明式队列
             * 参数1:列队名称
             * 参数2:是否定义持久化队列
             * 参数3:是否独占本次连接
             * 参数4:是否在不使用的时候自动删除队列
             * 参数5:队列其他参数
             */
            channel.queueDeclare("simple_queue",true,false,false,null);
            //创建消费者 并设置消息处理
            DefaultConsumer defaultConsumer=new DefaultConsumer(channel){
                /**
                 *
                 * @param consumerTag 消息者标签,在channel.basicConsumer时候可以指定
                 * @param envelope 消息包的内容,可从中获取消息id,消息routingkey,交换机,消息和重传标志(收到消息后是否需要重新发送)
                 * @param properties 属性消息
                 * @param body 消息
                 * @throws IOException
                 */
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    //路由的key
                   String routingKey = envelope.getRoutingKey();
                    //获取交换机信息
                   String exchange = envelope.getExchange();
                    //获取消息id
                    long deliveryTag = envelope.getDeliveryTag();
                    //获取消息信息
                   String  message = new String(body,"UTF-8");
                   //测试
                    System.out.println("routingKey:"+routingKey);
                    System.out.println("exchange:"+exchange);
                    System.out.println("deliveryTag:"+deliveryTag);
                    System.out.println("message:"+message);
                }
            };
            /**
             * 消息监听
             * 参数1:队列名称
             * 参数2:是否自动确认,设置为true表示收到自动像mq回复收到了,mq接受到回复会删除消息,设置为false则需要手动确认
             * 参数3:消息收到后回调
             */
            channel.basicConsume("simple_queue",true,defaultConsumer);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}

运行结果:

springboot rabbitMQ 消息对象_rabbitmq_04

最后咱们那个消息手动确认机制 啥时候手动 啥时候自动嘞:

/*
             * 消息监听
             * 参数1:队列名称
             * 参数2:是否自动确认,设置为true表示收到自动像mq回复收到了,mq接受到回复会删除消息,设置为false则需要手动确认
             * 参数3:消息收到后回调
             */
            channel.basicConsume("simple_queue",true,defaultConsumer);

对于不是很重要的消息,丢失了对咱的系统没啥影响的话 咱们可以使用自动Ack会比较方便。

对于很重要的消息,不允许该消息丢失的情况下那么我们就应该使用手动Ack来进行消息确认,防止消息丢失。