RabbitMQ 11:原生Java客户端+消息的属性+Request-Response模式

97 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

1.创建生产者ReplyToProducer

在这里插入图片描述

package com.rabbit.fisher.setmsg;

import com.rabbitmq.client.*;

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

/**
 *消息的属性控制
 */
public class ReplyToProducer
{

    public final static String EXCHANGE_NAME="replyto";

    public static void main( String[] args ) throws IOException, TimeoutException {
        //创建链接、连接到MQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接工厂的连接地址(默认端口5672)
        connectionFactory.setHost("192.168.42.111");
        //设置虚拟主机
        connectionFactory.setVirtualHost("fisher");
        //设置用户名
        connectionFactory.setUsername("fisher");
        //设置密码
        connectionFactory.setPassword("123456");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建信道
        Channel channel = connection.createChannel();
        //在信道中设置交换器(这里选择直接交换器direct)
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //响应QueueName,消费者将会把要返回的信息发送到该Queue
        String responseQueue = channel.queueDeclare().getQueue();
        //申明一个消费者
        final Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("Receive[" + envelope.getRoutingKey() + "]" + message);
            }
        };
        //消费者应答队列上的消息
        channel.basicConsume(responseQueue, true, consumer);

        //消息的唯一ID
        String msgId = UUID.randomUUID().toString();
        //设置消息中的应答属性
        AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().replyTo(responseQueue).messageId(msgId).build();
        //申明路由键及消息体
        String route ="error";
        String msg = "Hello World";
        //发布消息(设置交换器、路由键、参数、消息内容)
        channel.basicPublish(EXCHANGE_NAME, route, properties, msg.getBytes());
        System.out.println("Send:" + route + ";" + msg);
    }
}

replyTo属性构建回复消息的私有响应队列,在生产者中,先申明一个队列responseQueue,用于消费者将返回的消息发送到这个队列中,再将这个队列名称添加到属性properties中,供消费者使用,最后在发送消息时,把属性properties作为入参传入。

在这里插入图片描述 在生产者中,申明一个消费者,用于完成第4步,获取应答消息,而且消费的是发送消息使用的同一个队列responseQueue 在这里插入图片描述

2.创建一个消费者ReplyToConsumer

package com.rabbit.fisher.setmsg;

import com.rabbitmq.client.*;

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

/**
 *消息属性的控制
 */
public class ReplyToConsumer
{

    public static void main( String[] args ) throws IOException, TimeoutException {
        //创建链接、连接到MQ
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接工厂的连接地址(默认端口5672)
        connectionFactory.setHost("192.168.42.111");
        //设置虚拟主机
        connectionFactory.setVirtualHost("fisher");
        //设置用户名
        connectionFactory.setUsername("fisher");
        //设置密码
        connectionFactory.setPassword("123456");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //创建信道
        final Channel channel = connection.createChannel();
        //在信道中设置交换器
        channel.exchangeDeclare(ReplyToProducer.EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //申明队列
        String queueName = channel.queueDeclare().getQueue();

        //绑定:将队列与交换器通过路由键绑定
        String routeKey = "error";
        channel.queueBind(queueName, ReplyToProducer.EXCHANGE_NAME, routeKey);
        System.out.println("waiting for message ......");

        //申明一个消费者
        final Consumer consumer = new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("Receive[" + envelope.getRoutingKey() + "]" + message);
                //从消息中拿到相关属性(确定要应答的消息ID)
                AMQP.BasicProperties responseProperties = new AMQP.BasicProperties.Builder().replyTo(properties.getReplyTo())
                        .correlationId(properties.getMessageId()).build();
                //消费者要消费时,同时需要作为生产者生产消息
                channel.basicPublish("", responseProperties.getReplyTo(), responseProperties, ("Feedback," + message).getBytes());
            }
        };
        //消费者在指定的队列上消费
        channel.basicConsume(queueName, true, consumer);
    }
}

在这里插入图片描述

3.先启动消费者

在这里插入图片描述

4.再启动生产者,查看生产者打印

在这里插入图片描述

5.查看消费者打印

在这里插入图片描述