RabbitMQ 入门 (二)——创建一个基本的消息队列(点对点模式)

上一篇文章:RabbitMQ环境的搭建(一)——CentOS7下安装rabbitMQ环境

Virtual Host的作用

开始之前我们先要强调一个概念 Virtual Host 。Virtual Host是什么作用呢?有什么作用呢?
在 RabbitMQ 中,Virtual Host 可以理解为Mysql 中的库名的作用

  1. 用于隔离不同项目,解决命名冲突
  2. 用户权限分配的最小粒度

比如现在我一个公司有多个项目需要用到MQ,那么我可能在开发环境的情况下,不同项目用到的 MQ 服务器为同一台,而且不同项目之间就通过这个 Visual Host 来区分,不同的 Virtual Host 之间可以有相同的交换机或者是队列命名,并且不同 vhost 下面的 Exchange, Queue,Message 是不能互通的。(比如Mysql中 db1 和 db2 两个不同的库,都有同名的 User 表,)
RabbitMQ在给用户分配操作权限时,需要通过给用户分配在不同 vhost 的权限,但是不能分权限到Exchange或者Queue上面
rabbitmqctl.bat set_permissions -p <vhost> <username> <permissions>

创建 VHost

在这里插入图片描述
这里我都输入为 /HelloWorld , 可以VHost添加成功 注意一定VHost一定要加上 / ,避免之后连接报错
在这里插入图片描述

创建用于这个 VHost 的用户

由于之前我创建的 admin 用户是整个rabbitMq 的管理员用户,拥有的权限太高,不适合用于开发,这里我们专门来创建一个用户用于HelloWorld 这个 VHost。
在这里插入图片描述
这里我创建了一个 hello 用户,可以看到现在还没有该用户可以访问的VHost
在这里插入图片描述
那我们点击 hello 这个名字去设置该用户的权限
在这里插入图片描述
然后程序里面就可以用这个用户来进行消息通讯了。

创建一个 HelloWorld 队列
在这里插入图片描述
创建成功后如下图所示在这里插入图片描述

用 Maven 搭建最基本的生产者和消费者

引入maven依赖

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

创建连接代码


/**
 * RabbitMQ 连接类,用于建立与RabbitMQ Server端的连接
 * 官方文档地址:http://previous.rabbitmq.com/v3_5_7/tutorials/tutorial-one-java.html
 *
 */
public class RabbitMQConnection {

    public static String RABBIT_MQ_SERVER_HOST = "192.168.199.240";

    public static int RABBIT_MQ_SERVER_PORT = 5672;

    public static String VIRTUAL_HOST = "/HelloWorld";


    /**
     * 获取RabbitMQ连接
     * @return
     */
    public static Connection getConnection() throws IOException, TimeoutException {
        //1、创建连接
        ConnectionFactory factory = new ConnectionFactory();
        //2、设置主机名
        factory.setHost(RABBIT_MQ_SERVER_HOST);
        //3、设置通讯端口,默认是5672,不专门设置也可以
        //factory.setPort(RABBIT_MQ_SERVER_PORT);
        //4、设置账号和密码
        factory.setUsername("hello");
        factory.setPassword("123456");
        //4、设置Virtual Host
        factory.setVirtualHost(VIRTUAL_HOST);
        //5、创建连接
        return factory.newConnection();
    }
}

生产者代码


/**
 * 生产者
 */
public class Producer {

    private static final String QUEUE_NAME = "HelloWorld";

    public static void main(String[] args) throws IOException, TimeoutException {

        while (true) {
            System.out.println("请输入消息:");
            Scanner scanner = new Scanner(System.in);
            //1、创建连接
            Connection connection = RabbitMQConnection.getConnection();
            //2、创建通道
            Channel channel = connection.createChannel();
            //3、发送消息,这里使用Scanner通过控制台输入的内容来作为消息
            //nextLine() 以回车结束当前的输入,会接收空格
            String message = scanner.nextLine();
            /*
            参数说明:
            exchange:当期尚未指定exchange,又不能为null,只能设置为一个空字符串
            routingKey: 就是队列名称
            props:消息的额外属性
            body: 消息主体
             */
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            System.out.println("消息已被发送:" + message);
            //发送完记得关闭连接
            channel.close();
            connection.close();
        }
    }
}

消费者代码


/**
 * 消费者
 */
public class Consumer {

    private static final String QUEUE_NAME = "HelloWorld";

    public static void main(String[] args) throws IOException, TimeoutException {
        // 1、创建连接
        Connection connection = RabbitMQConnection.getConnection();
        // 2、创建通道
        Channel channel = connection.createChannel();
        // 3、设置队列的消费逻辑
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
            //接收到一个消息时会使用这个方法,这里进行重写,用来输出接收到的消息
            /*
            参数说明:
            consumerTag:消费者关联的标签
            envelope: 消息包数据
            BasicProperties:消息的额外属性
            body: 消息主体,当前为二进制
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String messageBody = new String(body);
                System.out.println("消费者消费消息:"+messageBody);
            }
        };
        // 4、添加监听。队列需要在服务器中先创建好,不然启动会发生 NOT_FOUND - no queue 'HelloWorld'的错误
        // 开启自动确认,表示当消费者一旦接收到消息,队列就会把消息删除。无论消费者之后的处理是否报错
        channel.basicConsume(QUEUE_NAME,true, defaultConsumer);
    }
}

不同顺序启动和执行

先启动好生产者和消费者,然后生产消息

把生产者和消费者启动后:输入消息,能被监听到
在这里插入图片描述
在这里插入图片描述
一个最基本的消息已经创建成功和消费成功了。
在这里插入图片描述

先启动好生产者,然后生产消息,再启动消费者

在这里插入图片描述
此时能够在队列里面看到有两条消息在队列中(被持久化了,因为我们创建队列的时候,选择的是默认的支持持久化的选项)
在这里插入图片描述
然后启动停止掉生产者,再启动消费者。发现消费会被顺序消费掉。
在这里插入图片描述
然后队列里面的消息个数面板又变回了0
在这里插入图片描述

异常问题

  1. 设置权限后无法登陆,报 Not management user 错误
    在这里插入图片描述
    答:因为这时候的用户权限主要是在消息通讯,主要用于生产者和消费者。并没有 management 页面的权限。因此我们可以用分配了 administrator 的 admin 用户来进行界面管理。而没有分配角色的用来处理消息通讯。
    或者给 hello 用户分配角色 administrator
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值