RabbitMq-发送接收消息

下载安装:

        windows:  rabbit-mq官方文档:http://www.rabbitmq.com/install-windows.html

 发送/接收消息:

 1.引入的jar包:      

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

 2.创建RabbitConfig.java常量配置类

public class RabbitConfig {
    /**
     * 声明名为queue的队列名称
     */
    public static final String queue = "queue";
}

 3.创建执行发送消息类Send.java

   将消息发送到队列名:队列

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

public class Send {
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(RabbitConfig.queue,true, false, false, null);
        String message = "hello world!";
        System.out.println("server发送消息:" + message);
        channel.basicPublish("", RabbitConfig.queue, true, null, message.getBytes());
    }
}

  4.创建执行消息类Receive.java

     接收处理队列名:队列中的消息

import com.rabbitmq.client.*;

public class Receive {
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(RabbitConfig.queue,true, false, false, null);
        DeliverCallback deliverCallback = (consumerTag, delivery)->{
            long deliveryTag = delivery.getEnvelope().getDeliveryTag();
            String message = new String(delivery.getBody());
            System.out.println("client接收消息:" + message + ",deliveryTag:" + deliveryTag);
        };
        channel.basicConsume(RabbitConfig.queue, true, deliverCallback, (CancelCallback) null);
    }
}

 执行两个类的主要方法将会看到接收类接收到发送类中的消息:

到这里已经实现rabbitmq发送接收消息。下面简单解析方法参数的含义:

 1.声明队列queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)

     queue:队列名称

     durable:是否持久化, 队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使队列

                     持久化,保存到Erlang自带的Mnesia数据库中,当rabbitmq重启之后会读取该数据库

     exclusive:是否排外的。 两个作用:

                     (当设置true:只能存在一个消费者,声明队列连接关闭队列自动删除;false:多个消费者,连接关闭队列不会删除)

                     1.当关闭声明队列连接时connection.close()该队列是否会自动删除

                     2.该队列是否是私有的private,如果设置true,只能有一个消费者

     autoDelete:是否自动删除。当最后一个消费者断开连接之后,自动删除队列。

     arguments:map类型参数。下面表示map中key代表的含义

                          x-message-ttl:设置队列中的所有消息的生存周期

                          x-expires:当队列在指定的时间没有被访问,队列就会删除

                          x-max-length:限定队列的消息的最大值长度,超过指定长度将会把最早的几条删除掉

                          x-max-length-bytes:限定队列最大占用的空间大小

                          x-overflow:

                         x-dead-letter-exchange:当队列消息长度大于最大长度、或者过期的等,将从队列中删除的消息推送到指定的交换机中去而不是丢弃掉

                         x-dead-letter-routing-key:将删除的消息推送到指定交换机的指定路由键的队列中去

                         x-max-priority:优先级队列,声明队列时先定义最大优先级值(定义最大值一般不要太大),在发布消息的时候指定该消息的优先级, 优先级更高(数值更大的)的消息先被消费

                         x-queue-mode:Lazy Queues: 先将消息保存到磁盘上,不放在内存中,当消费者开始消费的时候才加载到内存中

                         x-queue-master-locator:

 2.发送消息:basicPublish(String exchange, String routingKey, boolean mandatory, BasicProperties props, byte[] body)

     exchange:指定交换机(rabbit中队列是在交换机exchange上绑定的,由交换机根据routingkey规则发送到指定队列)

     routingKey:路由键(将消息具体发送到交换机哪一个队列的策略/规则)

     mandatory:如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返还给生产者。false:出现上述情形broker会直接将消息扔掉

     props: 请参考:https://blog.csdn.net/vbirdbest/article/details/78698364

     body:消息内容

 3.接收消息:basicConsume(String queue, boolean autoAck, Consumer callback);

     queue:队列名字

     autoAck:是否自动确认消息,true自动确认,false 不自动要手动调用

     callback:实现Consumer接口:

package com.rabbitmq.client;

import com.rabbitmq.client.AMQP.BasicProperties;
import java.io.IOException;

public interface Consumer {
    void handleConsumeOk(String var1);

    void handleCancelOk(String var1);

    void handleCancel(String var1) throws IOException;

    void handleShutdownSignal(String var1, ShutdownSignalException var2);

    void handleRecoverOk(String var1);
    // 处理消息
    void handleDelivery(String var1, Envelope var2, BasicProperties var3, byte[] var4) throws IOException;
}

以上方法解析参考csdn 博主vbirdbest 链接:https://blog.csdn.net/vbirdbest/article/details/78670550

exchange交换机,routingkey路由,queue队列

简述:

rabbitmq中消息并不是直接将消息添加到队列中的,而是通过exchange(交换机)类型,以及 routingKey(路由)到exchange所绑定的queue队列中。

exchange类型特性_推荐参考此博客:https://blog.csdn.net/hry2015/article/details/79118804

routingKey和exchange搭配_推荐参考此博客:https://blog.csdn.net/hry2015/article/details/79183941

使用其中一种交换机类型direct(直连交换机),在上面发送消息代码中修改:

1.添加静态变量

public class RabbitConfig {
    /**
     * 声明名为queue的队列名称
     */
    public static final String queue = "queue2";
    /**
     * 交换机
     */
    public static final String directExchange = "directExchange";
    /**
     * 路由键
     */
    public static final String routingKey = "routingKey";
}

2.修改send类,添加交换机,绑定队列(共修改3处)

import static com.luck.rabbit.test.RabbitConfig.directExchange;
import static com.luck.rabbit.test.RabbitConfig.queue;
import static com.luck.rabbit.test.RabbitConfig.routingKey;
public class Send {
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(queue,true, false, true, null);
        
        // 1.创建direct交换机
        channel.exchangeDeclare(directExchange, BuiltinExchangeType.DIRECT);
        // 2.将队列queue绑定到交换机directExchange上,指定路由键为routingKey
        channel.queueBind(queue, directExchange, routingKey);

        String message = "hello world!";
        System.out.println("server发送消息:" + message);
        // 3.发送消息到directExchange交换机,路由键为routingKey
        channel.basicPublish(directExchange, routingKey, true, null, message.getBytes());
    }
}

3.Receive类可以不修改,但是因为队列名字改变了,需要重新运行此类

以上实现了,向direct交换机发送消息到绑定路由键为routingKey的队列queue。

Channel接口中的两个方法获取消息:basicGet(pull) / basicConsume(push)

public class Receive {
    public static void main(String[] args) throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(queue,true, false, true, null);
        System.out.println("waiting for messages");
        // 更换获取消息方式
        pull(channel);
    }
    /**
     * 拉取:主动获取消息
     * @param channel
     */
    public static void pull(Channel channel) throws Exception {
        String message;
        GetResponse resp ;
        resp = channel.basicGet(queue,true);
        if(resp==null){
            System.out.println(queue+" 队列无消息");
            return;
        }
        message = new String(resp.getBody(), "UTF-8");
        System.out.println("获取消息:"+ message);
        channel.close();
    }

    /**
     * 推送:轮训获取消息
     * @param channel
     */
    public static void push(Channel channel){
        DeliverCallback deliverCallback = (consumerTag, delivery)->{
            long deliveryTag = delivery.getEnvelope().getDeliveryTag();
            String messages = new String(delivery.getBody());
            System.out.println("client接收消息:" + messages + ",deliveryTag:" + deliveryTag);
        };
        try {
            channel.basicConsume(queue, true, deliverCallback, (CancelCallback) null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37751454/article/details/85006459