RabbitMQ使用

简单使用:

在这里插入图片描述

创建一个空工程来容纳所有的子模块:

子maven模块名字:rabbitmq-hello

需要的依赖:

<dependencies>
        <!--rabbitmq依赖客户端-->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.8.0</version>
        </dependency>
        <!--操作文件流的一个依赖-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!--指定jdk编译版本-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

在这里插入图片描述

在这里插入图片描述

创建类:com.fan.rabbitmq.one.Producer

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

生产者:

package com.fan.rabbitmq.one;

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

public class Producer {
    //队列名称
    public static final String QUEUE_NAME= "hello";
    //发消息
    public static void main(String[] args) throws Exception {
        //创建一个连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //工厂ip连接rabbitmq的队列
        connectionFactory.setHost("192.168.211.200");
        //用户名
        connectionFactory.setUsername("admin");
        //密码
        connectionFactory.setPassword("123");
        //创建连接
        Connection connection = connectionFactory.newConnection();
        //获取消息通道
        Channel channel = connection.createChannel();
        //生产一个队列:
        /**参数说明:
        1.队列名称
        2.对垒里面的消息是否需要持久化(磁盘),默认消息存到内存中
        3.改队列是否值提供一个消费者消费,是否消费共享,true可以多个消费者消费,false:只能一个消费者消费
        4.是否自动删除,最后一个消费者断开连接后,该队列是否自动删除,true:自动删除,false:不自动删除
        5.其他参数
        */
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        //发消息准备
        String msg = "hello world";
        //开始发送消息
        /**
        参数说明:1.发送到哪个交换机;2.漏由的key值,本次是队列的名称;
        3.其他参数信息;4.发送消息的消息体
        */
        channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
        System.out.println("消息发送完毕");
    }
}

消费者:

package com.fan.rabbitmq.one;

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


public class Consumer {
    //队列名称
    public static final String QUEUE_NAME ="hello";
    //接收消息
    public static void main(String[] args) throws Exception {
        //创建mq中转连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //给连接工厂设置地址,用户名,密码等
        connectionFactory.setHost("192.168.211.200");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("123");
        //中转连接工厂创建连接(和快递发送方和送达方建立联系)
        Connection connection = connectionFactory.newConnection();
        //连接创建消息通道(创建快递运送通道)
        Channel channel = connection.createChannel();
        /*
        消费者消费消息参数说明:
        1.消费哪个队列
        2.消费成功后是否开启自动应答,true:自动应答,false:表示手动应答
        3.deliverCallback: 当一个消息发送过来后的回调接口
        4.消费者取消消费的回调
        */

        channel.basicConsume(QUEUE_NAME,
                true,
                (consumerTag,msg)->{ System.out.println("接收到的消息:"+new String(msg.getBody()) ); }
                ,(consumerTag)->{  System.out.println("消息的消费被中断"); }
          );

    }
}

测试:先开启发送消息,然后运行消费消息:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

工作队列:

在这里插入图片描述

在这里插入图片描述

实例:
在这里插入图片描述

抽下工具类RabbitMqUtils(在utils包下):

package com.fan.rabbitmq.utils;

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

public class RabbitMqUtils {
    //工具类的目的:得到一个消息通道channel
    public static Channel getChannel() throws Exception{
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.211.200");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("123");
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        return channel;
    }
}

工作队列消费者Work01Consumer:

package com.fan.rabbitmq.two;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;

public class Work01Consumer {
    //队列的名称
    public static final String QUEUE_NAME="hello";

    //接收消息
    /*
       消费者消费消息参数说明:
       1.消费哪个队列
       2.消费成功后是否开启自动应答,true:自动应答,false:表示手动应答
       3.deliverCallback: 当一个消息发送过来后的回调接口
       4.消费者取消消费的回调
       */
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.basicConsume(QUEUE_NAME,true,
                (consumerTag,msg)->{
                    System.out.println("接收到的消息:"+new String(msg.getBody()));
                },
                (consumerTag)->{
                    System.out.println(consumerTag+"消费者取消接口回调逻辑");
                }
                );

        System.out.println("c2启动,等待接收消息-----");
    }

}

工作队列生产者Worker01Product:

package com.fan.rabbitmq.two;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;

import java.util.Scanner;

public class Worker01Product {
    //队列名称
    public static final String QUEUE_NAME ="hello";

    public static void main(String[] args) throws Exception{
        Channel channel = RabbitMqUtils.getChannel();
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        //从控制台当中接收消息
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            String msg = scanner.next();
            /*
            发送一个消息:
            1.发送到哪个交换机
            2.漏由的key值是哪个,本次是队列的名称
            3.其他参数信息
            4.发送消息的消息体
            * */
            channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());
            System.out.println("发送消息完成:"+msg);
        }
    }
}

测试:

配置启动多个线程:

启动两个消费者c1和c2:
在这里插入图片描述

在这里插入图片描述
允许同一个类启动两次:

在这里插入图片描述

在这里插入图片描述

然后启动生产者:并发送消息
在这里插入图片描述

轮询消费消息:
在这里插入图片描述

在这里插入图片描述

消息应答:

在这里插入图片描述

消息自动应答:

在这里插入图片描述

消息手动应答:

手动应答的一些方法:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
批量应答图解:

在这里插入图片描述

消息自动重新入队:

为了保证消息的不丢失:

在这里插入图片描述

在这里插入图片描述

消息手动应答实例:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

消息生产者Task2Product :

package com.fan.rabbitmq.three;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import java.util.Scanner;

public class Task2Product {
    //队列名称
    public static final String TASK_QUEUE_ANME = "ack_queue";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //队列声明
        channel.queueDeclare(TASK_QUEUE_ANME,false,false,false,null);
        //从控制台输入信息
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            String msg = scanner.next();
            channel.basicPublish("",TASK_QUEUE_ANME,null,msg.getBytes("UTF-8"));
            System.out.println("生产者发出消息:"+msg);
        }
    }
}

消息的消费者1:Task2Consumer:

package com.fan.rabbitmq.three;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//手动应答,保证消息的不丢失
public class Task2Consumer {
    //消息队列
    public static final String TASK_QUEUE_NAME = "ack_queue";
    //接收消息
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("c1等待接收消息处理时间较短");

        DeliverCallback deliverCallback = (consumerTag,msg)->{
            //沉睡一秒
            try {
                Thread.sleep(1*1000);
                System.out.println("接收到的消息:"+new String(msg.getBody(),"UTF-8"));
                //手动应答
                /*参数一:消息的标记tag
                * 参数二:是否批量应答false:不批量应答,true:批量*/
                channel.basicAck(msg.getEnvelope().getDeliveryTag(),false);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        //消费消息,并采用手动应答
        Boolean autoAck = false;
        channel.basicConsume(TASK_QUEUE_NAME,autoAck,deliverCallback,(ConsumerTag)->{
                    System.out.println(ConsumerTag+"消费者取消消息消费接口回调逻辑");
                });
    }
}

消息的消费者2:Task2Consumer2:

package com.fan.rabbitmq.three;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//手动应答,保证消息的不丢失
public class Task2Consumer2 {
    //消息队列
    public static final String TASK_QUEUE_NAME = "ack_queue";
    //接收消息
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
      System.out.println("c2等待接收消息处理时间较长。。。。。。。。。。。。。。。");

        DeliverCallback deliverCallback = (consumerTag,msg)->{
            //沉睡一秒
            try {
                Thread.sleep(30*1000);
                System.out.println("接收到的消息:"+new String(msg.getBody(),"UTF-8"));
                //手动应答
                /*参数一:消息的标记tag
                 * 参数二:是否批量应答false:不批量应答,true:批量*/
                channel.basicAck(msg.getEnvelope().getDeliveryTag(),false);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        //消费消息,并采用手动应答
        Boolean autoAck = false;
        channel.basicConsume(TASK_QUEUE_NAME,autoAck,deliverCallback,(ConsumerTag)->{
            System.out.println(ConsumerTag+"消费者取消消息消费接口回调逻辑");
        });
    }
}

在这里插入图片描述

测试:
生产者发送消息:
在这里插入图片描述
消费者1接收消息;
在这里插入图片描述
消费者2接收消息:
在这里插入图片描述

然后消息bb没有丢失,而是给消费者1去处理了:

在这里插入图片描述

RabbitMQ持久化:

持久化概念:

在这里插入图片描述

队列持久化:

在这里插入图片描述

在这里插入图片描述

删除已存在的非持久化队列:
在这里插入图片描述

消息持久化:

在这里插入图片描述

持久化代码:
channel.basicPublish("",TASK_QUEUE_ANME, MessageProperties.PERSISTENT_TEXT_PLAIN
,msg.getBytes(“UTF-8”));

在这里插入图片描述

不公平分发:

在这里插入图片描述

设置成1为不公平分发,0为默认的轮询分发。

在这里插入图片描述

修改消费者代码实现分发策略:因为消费方决定消息的消费方式

在这里插入图片描述

每个消费者都要设置:
在这里插入图片描述

测试:
发送多条消息:

在这里插入图片描述
消费者:
在这里插入图片描述

在这里插入图片描述

预取值:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.fan.rabbitmq.three;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

//手动应答,保证消息的不丢失
public class Task2Consumer2 {
    //消息队列
    public static final String TASK_QUEUE_NAME = "ack_queue";
    //接收消息
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("c2等待接收消息处理时间较长。。。。。。。。。。。。。。。");
        DeliverCallback deliverCallback = (consumerTag,msg)->{
            //沉睡一秒
            try {
                Thread.sleep(30*1000);
                System.out.println("接收到的消息:"+new String(msg.getBody(),"UTF-8"));
                //手动应答策略
                /*参数一:消息的标记tag
                 * 参数二:是否批量应答false:不批量应答,true:批量*/
                channel.basicAck(msg.getEnvelope().getDeliveryTag(),false);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        //消费消息,并采用手动应答
        Boolean autoAck = false;
        channel.basicQos(5);//1为设置不公平分发.basicQos参数为预取值
        channel.basicConsume(TASK_QUEUE_NAME,autoAck,deliverCallback,(ConsumerTag)->{
            System.out.println(ConsumerTag+"消费者取消消息消费接口回调逻辑");
        });
    }
}

在这里插入图片描述

在这里插入图片描述

发布确认:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

单个确认发布:

在这里插入图片描述

代码演示:

package com.fan.rabbitmq.four;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;

import java.util.UUID;

/*
发布确认模式:
使用的时间  :比较哪一种确认方式是最好的
*/
public class ConfimMsg {
    //消息总量MSG_COUNT
    public static final int MSG_COUNT = 1000;
    public static void main(String[] args) throws Exception {
        //1.单个确认
        publishMsgIndividually();//发布1000条单独确认消息,耗时694ms
        //2.批量确认

    }

    //1.单个确认
    public static void publishMsgIndividually()throws Exception{
        Channel channel = RabbitMqUtils.getChannel();
        //队列的声明
        String queueName = UUID.randomUUID().toString();
        channel.queueDeclare(queueName,true,false,false,null);
        //开启发布确认
        channel.confirmSelect();
        //开始时间
        long begin = System.currentTimeMillis();
        //批量发消息
        for (int i = 0; i < MSG_COUNT; i++) {
            String msg = i + "";
            channel.basicPublish("",queueName,null,msg.getBytes());
            //单个消息就马上进行发布确认
            boolean flag = channel.waitForConfirms();
            if(flag){
                System.out.println("消息发送成功");
            }
        }
        //结束时间
        long end = System.currentTimeMillis();
        System.out.println("发布"+MSG_COUNT+"条单独确认消息,耗时"+(end-begin)+"ms");
    }
}

批量确认发布:

在这里插入图片描述

package com.fan.rabbitmq.four;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;

import java.util.UUID;

/*
发布确认模式:
使用的时间  :比较哪一种确认方式是最好的
*/
public class ConfimMsg {
    //消息总量MSG_COUNT
    public static final int MSG_COUNT = 1000;
    public static void main(String[] args) throws Exception {
        //1.单个确认
        //publishMsgIndividually();//发布1000条单独确认消息,耗时694ms
        //2.批量确认
        BatchpublishMsg();//发布1000条,批量确认消息,耗时194ms

    }

    //2.批量确认
    public static void BatchpublishMsg()throws Exception{
        Channel channel = RabbitMqUtils.getChannel();
        //队列的声明
        String queueName = UUID.randomUUID().toString();
        channel.queueDeclare(queueName,true,false,false,null);
        //开启发布确认
        channel.confirmSelect();
        //开始时间
        long begin = System.currentTimeMillis();
        //每次批量确认消息的容量大小
        int batchSize = 100;
        //批量发消息
        for (int i = 0; i < MSG_COUNT; i++) {
            String msg = i + "";
            channel.basicPublish("",queueName,null,msg.getBytes());
            //这里进行批量确认操作:判断达到100个消息的时候,批量确认一次
            if(i % batchSize == 0){
                //批量发布确认
                channel.waitForConfirms();
            }
        }
        //结束时间
        long end = System.currentTimeMillis();
        System.out.println("发布"+MSG_COUNT+"条,批量确认消息,耗时"+(end-begin)+"ms");
    }
}

异步确认发布:

在这里插入图片描述

在这里插入图片描述
代码演示:

package com.fan.rabbitmq.four;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmCallback;
import java.util.UUID;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

/*
发布确认模式:
使用的时间  :比较哪一种确认方式是最好的
*/
public class ConfimMsg {
    //消息总量MSG_COUNT
    public static final int MSG_COUNT = 1000;
    public static void main(String[] args) throws Exception {
        //1.单个确认
        //publishMsgIndividually();//发布1000条单独确认消息,耗时694ms
        //2.批量确认
        //BatchpublishMsg();//发布1000条,批量确认消息,耗时194ms
        //3.异步确认
        publishMsgAsync();//发布1000条,批量确认消息,耗时66ms,第一次比较耗时

    }

    //异步发布确认
    public static void publishMsgAsync()throws Exception{
        Channel channel = RabbitMqUtils.getChannel();
        //队列的声明
        String queueName = UUID.randomUUID().toString();
        channel.queueDeclare(queueName,true,false,false,null);
        //开启发布确认
        channel.confirmSelect();
        /*
         线程安全有序的一个哈希表,适用于高并发的情况下
         1.轻松的将序号与消息进行关联
         2.轻松批量删除条目,只要给序号
         3.支持高并发(多线程)
        */
        ConcurrentSkipListMap<Long, String> outstandingConfirm = new ConcurrentSkipListMap<>();
        
        //消息确认成功,回调函数
        ConfirmCallback ackCallback = (deliverTag, multiple) -> {
            if(multiple){//批量确认
                //②.确定成功后,删除已经确认的消息,剩下的就是未确认的消息
                ConcurrentNavigableMap<Long, String> confirmed =
                        outstandingConfirm.headMap(deliverTag);
                confirmed.clear();
            }else{//单个确认
                outstandingConfirm.remove(deliverTag);
            }
            System.out.println("确认的消息:"+deliverTag);
        };
        /*
        消息确认失败,回调函数
        1.消息的标记
        2.消息是否为批量确认
        * */
        ConfirmCallback nackCallback = (deliverTag, multiple) -> {
            //③.打印一下未确认消息的都有哪些
            String msg = outstandingConfirm.get(deliverTag);
            System.out.println("未确认的消息是:"+msg+"未确认的消息tag:"+deliverTag);
        };
        //准备消息的监听器,监听哪些消息成功了,哪些消息失败了
        channel.addConfirmListener(ackCallback,nackCallback);//异步通知

        //开始时间
        long begin = System.currentTimeMillis();
        //批量发消息
        for (int i = 0; i < MSG_COUNT; i++) {
            String msg = "消息"+i;
            channel.basicPublish("",queueName,null,msg.getBytes());
            //①记录下所有要发送的消息到map,消息的总和
            outstandingConfirm.put(channel.getNextPublishSeqNo(),msg);
        }
        //结束时间
        long end = System.currentTimeMillis();
        System.out.println("发布"+MSG_COUNT+"条,批量确认消息,耗时"+(end-begin)+"ms");
    }
}

三种发布确认的速度比较:

在这里插入图片描述

交换机:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

绑定:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

交换机绑定队列:

在这里插入图片描述

fanout交换机:

fanout交换机即发布订阅模式:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
一个发送两个接收:
ReceiveLogs01将接收到的消息打印在控制台:

package com.fan.rabbitmq.five;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class ReceiveLogs01 {
    public static final String EXCHANGE_NAME = "logs";
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //声明一个临时队列,当消费者断开与队列的连接的时候,队列就自动删除
        String queueName = channel.queueDeclare().getQueue();
        //绑定交换机和队列
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        System.out.println("等待接收消息,把剩余的消息打印到屏幕上。。。。。。");
        DeliverCallback deliverCallback = (consumerTag, msg) -> {
            System.out.println("ReceiveLogs01控制台答应接收到的消息:" + new String(msg.getBody(), "utf-8"));
        };
        //消息的消费,包含取消消息是的回调接口
        channel.basicConsume(queueName,true,deliverCallback,(consumerTag)->{});
    }
}

消息的生产者:

package com.fan.rabbitmq.five;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import java.util.Scanner;

public class EmitLog {
    //交换机名称
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            String msg = scanner.next();
            channel.basicPublish(EXCHANGE_NAME,"",null,msg.getBytes("UTF-8"));
            System.out.println("生产者发出消息:"+msg);
        }
    }
}

测试:开启mq的linux服务,
然后启动三个main程序:
在这里插入图片描述
两个消费者都能接收到一份消息:

在这里插入图片描述

在这里插入图片描述

direct交换机:

direct交换机即漏由模式:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

实战:
在这里插入图片描述

在这里插入图片描述
消费者ReceiveLogsDirect01:

package com.fan.rabbitmq.six;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class ReceiveLogsDirect01 {
    //声明交换机名字
    public static final String EXCHANGE_NAME="direct_logs";

    public static void main(String[] args)throws Exception {
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        //2.交换机的声明创建(参数一时交换机的名字,参数二是交换机的类型)
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //3.队列的声明创建
        channel.queueDeclare("console",false,false,false,null);
        //4.队列的绑定(队列名,交换机名,漏由key),可以绑定多个
        channel.queueBind("console",EXCHANGE_NAME,"info");
        channel.queueBind("console",EXCHANGE_NAME,"warning");
        //接收消息回调函数
         DeliverCallback  deliverCallback = (consumerTag, msg) -> {
            System.out.println("ReceiveLogsDirect01控制台打印接收到的消息:"+
                    new String(msg.getBody(),"UTF-8"));
        };
         //消息消费(消费者取消消息时回调接口)
        channel.basicConsume("console",true,deliverCallback,(consumerTag)->{});

    }
}

消费者ReceiveLogsDirect02 :

package com.fan.rabbitmq.six;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class ReceiveLogsDirect02 {
    //声明交换机名字
    public static final String EXCHANGE_NAME="direct_logs";

    public static void main(String[] args)throws Exception {
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        //2.交换机的声明创建(参数一时交换机的名字,参数二是交换机的类型)
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //3.队列的声明创建
        channel.queueDeclare("disk",false,false,false,null);
        //4.队列的绑定(队列名,交换机名,漏由key),可以绑定多个
        channel.queueBind("disk",EXCHANGE_NAME,"error");
        //接收消息回调函数
         DeliverCallback  deliverCallback = (consumerTag, msg) -> {
            System.out.println("ReceiveLogsDirect02控制台打印接收到的消息:"+
                    new String(msg.getBody(),"UTF-8"));
        };
         //消息消费(消费者取消消息时回调接口)
        channel.basicConsume("disk",true,deliverCallback,(consumerTag)->{});

    }
}

生产者:

package com.fan.rabbitmq.six;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;

import java.util.Scanner;

public class DirectLogs {
    //声明交换机名字
    public static final String EXCHANGE_NAME="direct_logs";

    public static void main(String[] args) throws Exception{
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        //2.循环发送消息
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            String msg = scanner.next();
            channel.basicPublish(EXCHANGE_NAME,"error",
                    null,msg.getBytes("UTF-8"));
            System.out.println("生产者发出消息:"+msg);
        }
    }
}

测试:发送给带有漏由口令error的消息,则只能被队列2接收到(即ReceiveLogsDirect02类中绑定了队列disk,口令是error)。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

topics交换机:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

注意:
在这里插入图片描述

在这里插入图片描述

消费者:ReceiveLogsTopic01 :

package com.fan.rabbitmq.seven;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class ReceiveLogsTopic01 {
    //交换机名称
    public static final String EXCHANGE_NAME = "topic_logs";
    //接收消息
    public static void main(String[] args)throws Exception {
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        //2.交换机的声明创建
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //3.队列的声明创建
        String queueName = "Q1";
        channel.queueDeclare(queueName,false,false,false,null);
        //4.队列的绑定
        channel.queueBind(queueName,EXCHANGE_NAME,"*.orange.*");
        System.out.println("等待接收消息。。。。。");

        DeliverCallback deliverCallback = (consumerTag, msg) -> {
            System.out.println(new String(msg.getBody(),"UTF-8") );
            System.out.println("接收队列:"+queueName+",绑定键:"+
                    msg.getEnvelope().getRoutingKey());
        };
        //接收消息
        channel.basicConsume(queueName,true,deliverCallback,(consumerTag)->{});
    }
}

消费者:ReceiveLogsTopic02 :

package com.fan.rabbitmq.seven;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class ReceiveLogsTopic02 {
    //交换机名称
    public static final String EXCHANGE_NAME = "topic_logs";
    //接收消息
    public static void main(String[] args)throws Exception {
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        //2.交换机的声明创建
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //3.队列的声明创建
        String queueName = "Q2";
        channel.queueDeclare(queueName,false,false,false,null);
        //4.队列的绑定
        channel.queueBind(queueName,EXCHANGE_NAME,"*.*.rabbit");
        channel.queueBind(queueName,EXCHANGE_NAME,"lazy.#");
        System.out.println("等待接收消息。。。。。");

        DeliverCallback deliverCallback = (consumerTag, msg) -> {
            System.out.println(new String(msg.getBody(),"UTF-8") );
            System.out.println("接收队列:"+queueName+",绑定键:"+
                    msg.getEnvelope().getRoutingKey());
        };
        //接收消息
        channel.basicConsume(queueName,true,deliverCallback,(consumerTag)->{});
    }
}

生产者:EmitLogTopic :

package com.fan.rabbitmq.seven;

import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import java.util.HashMap;
import java.util.Map;

public class EmitLogTopic {
    //交换机名称
    public static final String EXCHANGE_NAME="topic_logs";

    public static void main(String[] args)throws Exception {
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        HashMap<String, String> map = new HashMap<>();
        map.put("lazy.orange.elephant","被队列Q1Q2接收到");
        map.put("quick.orange.fox","被队列Q1接收到");
        map.put("lazy.brown.fox","被队列Q2接收到");
        map.put("lazy.pink.ribbit","满足两个绑定,但是只能被队列Q2接收到");
        map.put("quick.brown.fox","不满足任何绑定,不会被任何队列接收到,会被丢弃");
        map.put("quick.orange.male.rabbit","四个单词不匹配任何的绑定队列,会被丢弃");
        map.put("lazy.orange.male.rabbit","是四个单词,但匹配Q2");
        for (Map.Entry<String, String> bindingKeyEntry : map.entrySet()) {
            String routingKey = bindingKeyEntry.getKey();
            String msg = bindingKeyEntry.getValue();
            channel.basicPublish(EXCHANGE_NAME,routingKey,null,
                    msg.getBytes("UTF-8"));
            System.out.println("生产者发出消息:"+msg);
        }
    }
}

然后启动测试即可;

死信队列:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

消息过期:

消费者Consumer1:

package com.fan.rabbitmq.eight;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import java.util.HashMap;

public class Consumer1 {
    //普通交换机的名字
    public static final String NORMAL_EXCHANGE = "normal_exchange";
    //死信交换机的名字
    public static final String DEAD_EXCHANGE = "dead_exchange";
    //普通队列的名称
    public static final String NORMAL_QUEUE = "normal_queue";
    //死信队列的名称
    public static final String DEAD_QUEUE = "dead_queue";

    public static void main(String[] args) throws  Exception{
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        //2.交换机的声明创建
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
        //3.队列的声明创建
        //#########################声明普通队列########################################
        HashMap<String, Object> arguments = new HashMap<>();
        //设置ttl过期时间,可以在这里设置,但是不建议,因为不灵活10s=10 000ms
        //arguments.put("x-message-ttl",10000);
        //正常队列设置死信交换机,发生异常的时候连接死信交换机
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置死信的routing-key
        arguments.put("x-dead-letter-routing-key","lisi");
        //正常队列有异常消息时进入死信队列
        channel.queueDeclare(NORMAL_QUEUE,true,false,false,arguments);
        //#########################声明死信队列########################################
        channel.queueDeclare(DEAD_QUEUE,true,false,false,null);
        //绑定普通的交换机与普通的队列
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
        //绑定死信的交换机与死信的队列
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");
        System.out.println("等待接收消息--------");
        //消费消息
        DeliverCallback deliverCallback = (consumerTag, msg) -> {
            System.out.println("Consumer1接收的消息是:"+
                    new String(msg.getBody(),"UTF-8"));
        };
        channel.basicConsume(NORMAL_QUEUE,true,deliverCallback,(consumerTag)->{});
    }
}

消费者2:Consumer2:

package com.fan.rabbitmq.eight;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class Consumer2 {
    //死信队列的名称
    public static final String DEAD_QUEUE = "dead_queue";
    public static void main(String[] args) throws  Exception{
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("等待接收消息-------");
        //消息发送
        DeliverCallback deliverCallback = (consumerTag, msg) -> {
            System.out.println("Consumer2接收的消息是:"+
                    new String(msg.getBody(),"UTF-8"));
        };
        channel.basicConsume(DEAD_QUEUE,true,deliverCallback,(consumerTag)->{});
    }
}

生产者Producer:

package com.fan.rabbitmq.eight;
import com.fan.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;

public class Producer {
    //声明普通交换机的名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";

    public static void main(String[] args)throws Exception {
        //1.获取信道
        Channel channel = RabbitMqUtils.getChannel();
        //死信消息,设置ttl(time to live:存活时间)时间,单位是ms
        AMQP.BasicProperties properties = new AMQP.BasicProperties()
                .builder().expiration("10000").build();
        for (int i = 1; i <= 10 ; i++) {
            String msg = "info" + i;
            //发消息
            channel.basicPublish(NORMAL_EXCHANGE,"zhangsan",properties,
                    msg.getBytes("UTF-8"));
        }
    }
}

测试:

先启动Consumer1消费者,然后立马停掉(模拟死掉),然后启动生产者来发送10条消息。看MQ网页控制台:

在这里插入图片描述

在这里插入图片描述

然后启动消费者Consumer2,看控制台10条消息被C2消费掉:
在这里插入图片描述

队列达到最大长度:

在这里插入图片描述

在这里插入图片描述
修改代码:
在这里插入图片描述

在这里插入图片描述

测试:

同样,启动消费者01后直接关闭,然后启动生产者,看效果:
在这里插入图片描述

消息被拒:

修改代码:
在这里插入图片描述

启动消费者01,然后启动生产者,看控制台:

在这里插入图片描述

然后启动消费者02看控制台:
在这里插入图片描述

在这里插入图片描述

延迟队列:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值