4、RabbitMQ学习笔记—消息对列的使用

消息的生产与发送

  1. 获取连接工厂 ConnectionFactory
  2. 获取连接 Connection
  3. 创建通信信道 Channel
  4. 声明队列 Queue
  5. 创建生产者、消费者 Producer、Consumer
    我们接下来的代码演示使用idea 创建springboot maven项目进行。
    依赖
		<dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>4.8.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit</artifactId>
            <version>2.1.6.RELEASE</version>
        </dependency>

1、编写连接工厂

public class ConnectionsUtils {
    /**
     * 获取MQ的连接
     */
    public static Connection getConnection() throws IOException, TimeoutException {
        // 连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        // 设置服务ip
        factory.setHost("127.0.0.1");
        // 设置服务端口
        factory.setPort(5672);
        return factory.newConnection();
    }
}

// 通过查看ConnectionFactory源码可以发现设置了默认的一些配置信息,因此我们在这只定义了服务ip和端口号
在这里插入图片描述
2、创建消息生产者并发送消息

    private static final String routingKey= "test_simple_queue";	
    public static void main(String[] args) throws IOException, TimeoutException {
        //获取一个连接
        Connection connection = ConnectionsUtils.getConnection();
        //从连接获取通道
        Channel channel = connection.createChannel();
        String msg = "hello simple message";
        channel.basicPublish("", routingKey,null, msg.getBytes());
        System.out.println("--send msg-- " + msg);
        // *使用完毕后务必关闭通道和连接!*
        channel.close();
        connection.close();
    }

发送消息方法:

    /**
     * Publish a message.
     *
     * Publishing to a non-existent exchange will result in a channel-level
     * protocol exception, which closes the channel.
     *
     * Invocations of <code>Channel#basicPublish</code> will eventually block if a
     * <a href="http://www.rabbitmq.com/alarms.html">resource-driven alarm</a> is in effect.
     *
     * @see com.rabbitmq.client.AMQP.Basic.Publish
     * @see <a href="http://www.rabbitmq.com/alarms.html">Resource-driven alarms</a>
     * @param exchange the exchange to publish the message to  发送至哪个交换机
     * @param routingKey the routing key   路由键
     * @param props other properties for the message - routing headers etc 消息组成部分
     * @param body the message body 消息组成部分
     * @throws java.io.IOException if an error is encountered
     */
    void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;

3、创建消费者接收消息

	private static final String QUEUE_NAME = "test_simple_queue";
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionsUtils.getConnection();
        // 创建频道
        Channel channel = connection.createChannel();
        // 队列声明
        channel.queueDeclare(QUEUE_NAME, true, false, false ,null);
        //定义消费者
        DefaultConsumer consumer = new DefaultConsumer(channel){
            // 重写监听
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body,"utf-8");
                System.out.println("msg: "+msg);
                System.out.println("consumerTag: "+consumerTag);
                System.out.println("properties: "+properties);
                System.out.println("msg: "+msg);
            }
        };
        // 事件监听
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }

声明队列方法:

/**
     * Declare a queue
     * @see com.rabbitmq.client.AMQP.Queue.Declare
     * @see com.rabbitmq.client.AMQP.Queue.DeclareOk
     * @param queue the name of the queue 队列名称
     * @param durable true if we are declaring a durable queue (the queue will survive a server restart) 是否持久化这个队列,true的话,该队列在服务重启后依然存在
     * @param exclusive true if we are declaring an exclusive queue (restricted to this connection) 独占(顺序消费,只有当前连接才可以监听该队列)
     * @param autoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use) 自动删除队列
     * @param arguments other properties (construction arguments) for the queue 一些其他的参数
     * @return a declaration-confirm method to indicate the queue was successfully declared 
     * @throws java.io.IOException if an error is encountered
     */
    Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments) throws IOException;

重写接收消息方法:

    /**
     * Called when a <code><b>basic.deliver</b></code> is received for this consumer.
     * @param consumerTag the <i>consumer tag</i> associated with the consumer与消费者关联的消费者标签
     * @param envelope packaging data for the message打包数据
     * @param properties content header data for the message消息头部信息
     * @param body the message body (opaque, client-specific byte array)消息体内容
     * @throws IOException if the consumer encounters an I/O error while processing the message
     * @see Envelope
     */
    void handleDelivery(String consumerTag,
                        Envelope envelope,
                        AMQP.BasicProperties properties,
                        byte[] body)
        throws IOException;
/**
     * Start a non-nolocal, non-exclusive consumer, with
     * a server-generated consumerTag.
     * @param queue the name of the queue
     * @param autoAck true if the server should consider messages
     * acknowledged once delivered; false if the server should expect
     * explicit acknowledgements
     * @param callback an interface to the consumer object
     * @return the consumerTag generated by the server
     * @throws java.io.IOException if an error is encountered
     * @see com.rabbitmq.client.AMQP.Basic.Consume
     * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
     * @see #basicConsume(String, boolean, String, boolean, boolean, Map, Consumer)
     */
    String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;

4、执行

  1. 首先我们运行消费者,完成消息队列的创建和保持监听状态来接收消息
  2. 启动消息发送者发送消息,如图所示已发送成功
    在这里插入图片描述
  3. 查看消费者端控制台发现,已经接收到消息并进行打印
    在这里插入图片描述
newConsumer: hello simple message
consumerTag: amq.ctag-YpoNNgCrIApZQPV_qHyYnA
properties: #contentHeader<basic>(content-type=null, content-encoding=null, headers=null, delivery-mode=null, priority=null, correlation-id=null, reply-to=null, expiration=null, message-id=null, timestamp=null, type=null, user-id=null, app-id=null, cluster-id=null)
msg: hello simple message

5、总结
上边代码我们可以发现一个问题,那就是消息生产者在发送消息的时候没有指定exchange,只指定了一个routingkey,而我们的消息消费者也接收到了消息,这是为什么呢?
这是因为,rabbitmq他有一个默认的exchange,如果在不指定exchange的时候,默认发送到该default exchange。
它的路由规则是根据routingkey去寻找和routingkey命名完全匹配的消息队列,找到后进行消息的发送。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值