RabbitMQ

1.概念

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

2、优势

2.1 应用解耦

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

2.2 异步提速

在这里插入图片描述

2.3 削峰填谷

在这里插入图片描述

3.MQ劣势

在这里插入图片描述

4. MQ 应用场景

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

5. RabbitMQ工作原理

在这里插入图片描述

5.1 AMQP介绍

在这里插入图片描述

5.2 RabbitMQ工作过程

在这里插入图片描述

5.3 工作原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
面试:
1、生产者与消息服务器建立TCP连接,会在内部建立虚拟信道,生产者发送消息是通过信道将消息发送给消息队列服务器中的交换机,服务器是多数的设计,里面有很多迷你的消息队列服务器— visual host, 不同的visual host中有很多交换机,队列等
通过binding 绑定规则发送给队列queue,消费者提前和队列queue建立好连接,使用信道进行通讯,

在这里插入图片描述

6. RabbitMQ 安装

6.1 基于Linux 安装

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

6.2 基于docker 安装

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

docker run -e RABBITMQ_DEFAULT_USER=guest  -e RABBITMQ_DEFAULT_PASS=123456  --name mq  --hostname mq1 -p 15672:15672  -p 5672:5672  -d  rabbitmq:3-management

7.RabbitMQ工作模式

在这里插入图片描述

7.1 简单模式

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

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>top.psjj</groupId>
    <artifactId>rabbitmq-study</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rabbitmq-study</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


加粗样式
在这里插入图片描述
**加粗样式**

package top.psjj.rabbitmqstudy.simple;

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

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

public class Producer {

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

        // 1、创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("101.227.52.230");
        factory.setPort(5672);
        factory.setVirtualHost("/root");
        factory.setUsername("root");
        factory.setPassword("root");
        // 2.创建连接
        Connection connection = factory.newConnection();
        // 3.创建信道
        Channel channel = connection.createChannel();
        // 4.声明队列
        channel.queueDeclare("simple_queue",false,false,false,null);
        // 5.发送消息
        channel.basicPublish("","simple_queue",null,"简单消息".getBytes());
        // 关闭资源
        channel.close();
        connection.close();


    }
}

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

package top.psjj.rabbitmqstudy.simple;

import com.rabbitmq.client.*;

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

public class SimpleConsumer {

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

        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("101.227.52.230");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/root");
        connectionFactory.setUsername("root");
        connectionFactory.setPassword("root");
        // 创建连接
        Connection connection = connectionFactory.newConnection();
        // 创建信道
        Channel channel = connection.createChannel();
        // 监听队列
        channel.basicConsume("simple_queue",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("输出消费的消息信息:"+new String(body));
            }
        });
    }
}


7.2 工作队列模式

在这里插入图片描述
代码实现:
工作队列生产者

package top.psjj.rabbitmqstudy.workqueue;

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

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

public class WorkQueueProduct {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 1.创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("101.227.52.230");
        factory.setPort(5672);
        factory.setVirtualHost("/root");
        factory.setUsername("root");
        factory.setPassword("root");

        // 2.创建连接
        Connection connection = factory.newConnection();
        // 3.创建信道
        Channel channel = connection.createChannel();
        // 4.创建队列 队列名,持久化,是否私有化,是否自动删除,是否添加额外参数
        channel.queueDeclare("work_queue",false,false,false,null);
        // 5.发送消息
        for (int i = 0; i < 100; i++) {
            String message = "(*^▽^*)发送消息(*^▽^*)"+i;
            // 交换机
            channel.basicPublish("","work_queue",null,message.getBytes());
        }
        // 6.关闭连接
        channel.close();
        connection.close();

    }
}

工作队列消费者
三个消费者同以下代码

package top.psjj.rabbitmqstudy.workqueue;

import com.rabbitmq.client.*;

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

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

        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("101.227.52.230");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/root");
        connectionFactory.setUsername("root");
        connectionFactory.setPassword("root");
        // 创建连接
        Connection connection = connectionFactory.newConnection();
        // 创建信道
        Channel channel = connection.createChannel();
        // 监听队列 工作队列名称,是否自动签发,消费消息
        channel.basicConsume("work_queue",true,new DefaultConsumer(channel){

            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:"+new String(body));
            }
        });
    }
}

输出结果:
在这里插入图片描述

7.3 发布订阅模式

在这里插入图片描述
生产者代码:
在这里插入图片描述
在这里插入图片描述

package top.psjj.rabbitmqstudy.pubsubFun;

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

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

/**
 * 发布订阅模式
 */
public class PubProducer {

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

        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("101.227.52.230");
        factory.setPort(5672);
        factory.setVirtualHost("/root");
        factory.setUsername("root");
        factory.setPassword("root");

        // 创建连接
        Connection connection = factory.newConnection();
        // 创建信道
        Channel channel = connection.createChannel();
        // 创建交换机 -- 交换机名,交换机类型,交换机持久化
        channel.exchangeDeclare("pub_sub_exchange", BuiltinExchangeType.FANOUT,true);
        // 创建队列--- 队列名,持久化,私有化,自动删除,额外参数
        channel.queueDeclare("send_email",false,false,false,null);
        channel.queueDeclare("send_message",false,false,false,null);
        channel.queueDeclare("send_station",false,false,false,null);
        // 绑定交换机--- 队列名,交换机名,路由关键字
        channel.queueBind("send_email","pub_sub_exchange","");
        channel.queueBind("send_message","pub_sub_exchange","");
        channel.queueBind("send_station","pub_sub_exchange","");
        // 发送消息-- 交换机名称,路由名称,额外参数,传递消息字节数组
        for (int i = 1; i <= 3; i++) {
            String message = "(*^▽^*)消息(*^▽^*)"+i;
            channel.basicPublish("pub_sub_exchange","",null,message.getBytes());
        }
        // 关闭连接
        channel.close();
        connection.close();
        System.out.println("发送成功!");

    }
}

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

package top.psjj.rabbitmqstudy.pubsubFun;

import com.rabbitmq.client.*;

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

public class SendStationConsumer {

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

        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("101.227.52.230");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/root");
        connectionFactory.setUsername("root");
        connectionFactory.setPassword("root");
        // 创建连接
        Connection connection = connectionFactory.newConnection();
        // 创建信道
        Channel channel = connection.createChannel();
        // 监听队列 工作队列名称,是否自动签发,消费消息
        channel.basicConsume("send_station",true,new DefaultConsumer(channel){

            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("站内消费者:"+new String(body));
            }
        });
    }
}

7.4 路由模式

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

路由模式生产者:

package top.psjj.rabbitmqstudy.route;

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

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

/**
 * 路由模式发布者
 */
public class RoutingProducer {

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

        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("101.227.52.230");
        factory.setPort(5672);
        factory.setVirtualHost("/root");
        factory.setUsername("root");
        factory.setPassword("root");

        // 创建连接
        Connection connection = factory.newConnection();
        // 创建信道
        Channel channel = connection.createChannel();
        // 创建交换机, 交换机名,类型,持久化
        channel.exchangeDeclare("routing_exchange", BuiltinExchangeType.DIRECT,true);
        // 声明队列
        channel.queueDeclare("routing_queue1",false,false,false,null);
        channel.queueDeclare("routing_queue2",false,false,false,null);
        // 绑定路由规则
        channel.queueBind("routing_queue1","routing_exchange","info");
        channel.queueBind("routing_queue1","routing_exchange","error");
        channel.queueBind("routing_queue2","routing_exchange","error");
        // 发送消息
        channel.basicPublish("routing_exchange","info",null,"(*^▽^*) (*^▽^*)".getBytes());
        channel.basicPublish("routing_exchange","error",null,"(灬ꈍ ꈍ灬) (灬ꈍ ꈍ灬)".getBytes());
        // 关闭资源
        channel.close();
        connection.close();
        System.out.println("发送成功");
    }
}

路由模式消费者

package top.psjj.rabbitmqstudy.route;

import com.rabbitmq.client.*;

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

/**
 * 路由模式消费者
 */
public class RoutingConsumer {

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

        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("101.227.52.230");
        factory.setPort(5672);
        factory.setVirtualHost("/root");
        factory.setUsername("root");
        factory.setPassword("root");

        // 创建连接
        Connection connection = factory.newConnection();
        // 创建信道
        Channel channel = connection.createChannel();
        // 监听队列
        channel.basicConsume("routing_queue1",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:"+new String(body));
            }
        });
    }
}


7.5 通配符模式

在这里插入图片描述
通配符生产者代码:

package top.psjj.rabbitmqstudy.topic;

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

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

public class TopicProducer {

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

        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("101.227.52.230");
        factory.setPort(5672);
        factory.setVirtualHost("/root");
        factory.setUsername("root");
        factory.setPassword("root");

        // 创建连接
        Connection connection = factory.newConnection();

        // 创建信道
        Channel channel = connection.createChannel();

        // 创建交换机 交换机名,通配符类型,是否持久化
        channel.exchangeDeclare("topic_exchange", BuiltinExchangeType.TOPIC,true);

        // 声明队列 队列名,是否持久化,是否私有化,是否自动删除,额外参数
        channel.queueDeclare("topic_queue1",true,false,false,null);
        channel.queueDeclare("topic_queue2",true,false,false,null);
        channel.queueDeclare("topic_queue3",true,false,false,null);

        // 绑定交换机和队列
        channel.queueBind("topic_queue1","topic_exchange","*.goods.*");
        channel.queueBind("topic_queue2","topic_exchange","#.goods.#");
        channel.queueBind("topic_queue3","topic_exchange","goods.#");

        // 发送消息  交换机名,路由规则,额外参数,发送的消息
        channel.basicPublish("topic_exchange","a.goods.sss",null,"消息1".getBytes());
        channel.basicPublish("topic_exchange","6.a.goods.sss.a.a.a",null,"消息2".getBytes());
        channel.basicPublish("topic_exchange","goods.666",null,"消息3".getBytes());

        // 关闭资源
        channel.close();
        connection.close();
    }
}

通配符消费者代码:

package top.psjj.rabbitmqstudy.topic;

import com.rabbitmq.client.*;

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

public class TopicConsumer {

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

        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("101.227.52.230");
        factory.setPort(5672);
        factory.setVirtualHost("/root");
        factory.setUsername("root");
        factory.setPassword("root");

        // 创建链接
        Connection connection = factory.newConnection();

        // 创建信道
        Channel channel = connection.createChannel();

        // 监听队列
        channel.basicConsume("topic_queue1",true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:"+new String(body));
            }
        });

    }
}

8.Springboot整合rabbitMQ

在这里插入图片描述

1.父工程POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.top.psjj</groupId>
    <artifactId>rabbitmq-study-2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rabbitmq-study-2</name>
    <packaging>pom</packaging>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.创建子模块
在这里插入图片描述
3.配置文件application.yml

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
# 日志
logging:
  pattern:
    console: '%d{HH:mm:ss.SSS}%clr(%-5level) --- [%-15thread]%cyan(%-50logger{50}):%msg%n'

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

在这里插入图片描述
在这里插入图片描述
4. 编写业务代码:
编写配置类:

package com.top.psjj.producer.config;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class RabbitMqConfig {

    /**
     * 简单消息队列
     * @return
     */
    @Bean("simple_queue")
    public Queue simpleQueue(){
        return QueueBuilder.durable("simple_queue").build();
    }
}

测试类,发送消息

package com.top.psjj.producer;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class SimpleMessageSendTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void test(){
        rabbitTemplate.convertAndSend("","simple_queue","hahahaha");
    }
}

5.消费者接受消息:
在这里插入图片描述

package com.top.psjj.consumer.mq.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ConsumerListener {

    @RabbitListener(queues = "simple_queue")
    public void simpleMessageListen(String message){
        System.out.println("简单消息:"+ message);
    }
}

6.启动消费者主启动类
在这里插入图片描述

8.1 应用小技巧

1、在application.yml中自定义配置信息
在这里插入图片描述
2、使用${}的形式去读取application.yml的配置信息
3、注入Enviroment 读取任意配置文件信息
在这里插入图片描述

8.2 工作模式

8.2.1 添加配置

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
# 日志
logging:
  pattern:
    console: '%d{HH:mm:ss.SSS}%clr(%-5level) --- [%-15thread]%cyan(%-50logger{50}):%msg%n'

rabbitmq:
  simple:
    queue: simple_queue
  workqueue:
    queue: work_queue

8.2.2 声明队列

package com.top.psjj.producer.config;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;


@Configuration
public class RabbitMqConfig {

    @Autowired  // 读取任意配置文件
    private Environment environment;

    /**
     * 简单消息队列
     * @return
     */
    @Bean("${rabbitmq.simple.queue}") // 通过${} 读取application.yml自定义配置
    public Queue simpleQueue(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.simple.queue")).build();
    }

    /**
     * 工作队列模式
     */
    @Bean("${rabbitmq.workqueue.queue}")
    public Queue workQueue(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.workqueue.queue")).build();
    }
}


8.2.3 发送消息

package com.top.psjj.producer;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

@SpringBootTest
public class SimpleMessageSendTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private Environment environment;

    @Test
    public void test() {
        rabbitTemplate.convertAndSend("", "simple_queue", "hahahaha");
    }

    @Test
    public void workQueueTest() {
        for (int i = 1; i <= 10; i++) {
            rabbitTemplate.convertAndSend("", environment.getProperty("rabbitmq.workqueue.queue"), "工作队列模式消息"+i);
        }
    }
}

8.2.4 添加消费者

package com.top.psjj.consumer.mq.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ConsumerListener {

    @RabbitListener(queues = "${rabbitmq.simple.queue}")
    public void simpleMessageListen(String message){
        System.out.println("简单消息:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue1(String message){
        System.out.println("工作消费任务1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue2(String message){
        System.out.println("工作消费任务2:"+ message);
    }
}

8.2.5 启动消费者主程序

测试结果:
在这里插入图片描述

8.3 发布订阅模式

8.3.1 编写配置文件

在这里插入图片描述

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
# 日志
logging:
  pattern:
    console: '%d{HH:mm:ss.SSS}%clr(%-5level) --- [%-15thread]%cyan(%-50logger{50}):%msg%n'

rabbitmq:
  simple:
    queue: simple_queue
  workqueue:
    queue: work_queue
  pubsub:
    exchange: pub_sub_exchange
    queue1: pub_sub_queue1
    queue2: pub_sub_queue2

8.3.2 声明队列和交换机

在这里插入图片描述

package com.top.psjj.producer.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;


@Configuration
public class RabbitMqConfig {

    @Autowired  // 读取任意配置文件
    private Environment environment;

    /**
     * 简单消息队列
     * @return
     */
    @Bean("${rabbitmq.simple.queue}") // 通过${} 读取application.yml自定义配置
    public Queue simpleQueue(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.simple.queue")).build();
    }

    /**
     * 工作队列模式
     */
    @Bean("${rabbitmq.workqueue.queue}")
    public Queue workQueue(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.workqueue.queue")).build();
    }

    /**
     * 发布订阅模式
     */
    @Bean("${rabbitmq.pubsub.exchange}")
    public Exchange pubsubExchange(){
        return ExchangeBuilder.fanoutExchange(environment.getProperty("rabbitmq.pubsub.exchange")).durable(true).build();
    }

    @Bean("${rabbitmq.pubsub.queue1}")
    public Queue pubsubQueue1(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.pubsub.queue1")).build();
    }

    @Bean("${rabbitmq.pubsub.queue2}")
    public Queue pubsubQueue2(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.pubsub.queue2")).build();
    }

    @Bean
    public Binding bindExchangeQueue1(){
        return BindingBuilder.bind(pubsubQueue1()).to(pubsubExchange()).with("").noargs();
    }

    @Bean
    public Binding bindExchangeQueue2(){
        return BindingBuilder.bind(pubsubQueue2()).to(pubsubExchange()).with("").noargs();
    }

}


8.3.3 发送消息

在这里插入图片描述

package com.top.psjj.producer;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

@SpringBootTest
public class SimpleMessageSendTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private Environment environment;

    @Test
    public void test() {
        rabbitTemplate.convertAndSend("", "simple_queue", "hahahaha");
    }

    @Test
    public void workQueueTest() {
        for (int i = 1; i <= 10; i++) {
            rabbitTemplate.convertAndSend("", environment.getProperty("rabbitmq.workqueue.queue"), "工作队列模式消息"+i);
        }
    }
}

8.3.4 编写消费者配置文件

和生产者配置文件内容一致

8.3.5 监听队列状态

在这里插入图片描述

package com.top.psjj.consumer.mq.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ConsumerListener {

    @RabbitListener(queues = "${rabbitmq.simple.queue}")
    public void simpleMessageListen(String message){
        System.out.println("简单消息:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue1(String message){
        System.out.println("工作消费任务1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue2(String message){
        System.out.println("工作消费任务2:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.pubsub.queue1}")
    public void pubsubConsumer1(String message){
        System.out.println("发布订阅模式1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.pubsub.queue2}")
    public void pubsubConsumer2(String message) {
        System.out.println("发布订阅模式2:" + message);
    }

}

8.3.6 运行消费者主启动类

在这里插入图片描述
结果如下
在这里插入图片描述

8.4 路由模式

8.4.1 配置文件

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
# 日志
logging:
  pattern:
    console: '%d{HH:mm:ss.SSS}%clr(%-5level) --- [%-15thread]%cyan(%-50logger{50}):%msg%n'

rabbitmq:
  simple:
    queue: simple_queue
  workqueue:
    queue: work_queue
  pubsub:
    exchange: pub_sub_exchange
    queue1: pub_sub_queue1
    queue2:
  routing:
    exchange: routing_exchange
    queue1: routing_queue1
    queue2: routing_queue2
    routingkey1: info
    routingkey2: error

8.4.2 声明队列和交换机

package com.top.psjj.producer.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;


@Configuration
public class RabbitMqConfig {

    @Autowired  // 读取任意配置文件
    private Environment environment;

    /**
     * 简单消息队列
     * @return
     */
    @Bean("${rabbitmq.simple.queue}") // 通过${} 读取application.yml自定义配置
    public Queue simpleQueue(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.simple.queue")).build();
    }

    /**
     * 工作队列模式
     */
    @Bean("${rabbitmq.workqueue.queue}")
    public Queue workQueue(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.workqueue.queue")).build();
    }

    /**
     * 发布订阅模式
     */
    @Bean("${rabbitmq.pubsub.exchange}")
    public Exchange pubsubExchange(){
        return ExchangeBuilder.fanoutExchange(environment.getProperty("rabbitmq.pubsub.exchange")).durable(true).build();
    }

    @Bean("${rabbitmq.pubsub.queue1}")
    public Queue pubsubQueue1(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.pubsub.queue1")).build();
    }

    @Bean("${rabbitmq.pubsub.queue2}")
    public Queue pubsubQueue2(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.pubsub.queue2")).build();
    }

    @Bean
    public Binding bindExchangeQueue1(){
        return BindingBuilder.bind(pubsubQueue1()).to(pubsubExchange()).with("").noargs();
    }

    @Bean
    public Binding bindExchangeQueue2(){
        return BindingBuilder.bind(pubsubQueue2()).to(pubsubExchange()).with("").noargs();
    }


    /**
     * 路由模式
     */
    @Bean("${rabbitmq.routing.exchange}")
    public Exchange routingExchange(){
        return ExchangeBuilder.directExchange(environment.getProperty("rabbitmq.routing.exchange")).durable(true).build();
    }

    @Bean("${rabbitmq.routing.queue1}")
    public Queue routingQueue1(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.routing.queue1")).build();
    }

    @Bean("${rabbitmq.routing.queue2}")
    public Queue routingQueue2(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.routing.queue2")).build();
    }

    @Bean
    public Binding bindRoutingExchangeQueue1(){
        return BindingBuilder.bind(routingQueue1()).to(routingExchange()).with(environment.getProperty("rabbitmq.routing.routingkey1")).noargs();
    }

    @Bean
    public Binding bindRoutingExchangeQueue2(){
        return BindingBuilder.bind(routingQueue2()).to(routingExchange()).with(environment.getProperty("rabbitmq.routing.routingkey2")).noargs();
    }

}

8.4.3 发布消息

package com.top.psjj.producer;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

@SpringBootTest
public class RoutingMessageTest {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private Environment environment;

    @Test
    public void test1(){
        rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.routing.exchange"),environment.getProperty("rabbitmq.routing.routingkey1"),"我的消息第一次发送看谁接受123");
    }

    @Test
    public void test2(){
        rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.routing.exchange"),environment.getProperty("rabbitmq.routing.routingkey2"),"我的消息第2次发送看谁接受666666");
    }
}

8.4.3 配置消费者application.yml

和生产者一样

8.4.4 监听队列

package com.top.psjj.consumer.mq.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ConsumerListener {

    @RabbitListener(queues = "${rabbitmq.simple.queue}")
    public void simpleMessageListen(String message){
        System.out.println("简单消息:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue1(String message){
        System.out.println("工作消费任务1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue2(String message){
        System.out.println("工作消费任务2:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.pubsub.queue1}")
    public void pubsubConsumer1(String message){
        System.out.println("发布订阅模式1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.pubsub.queue2}")
    public void pubsubConsumer2(String message) {
        System.out.println("发布订阅模式2:" + message);
    }

    @RabbitListener(queues = "${rabbitmq.routing.queue1}")
    public void routingConsumer1(String message){
        System.out.println("路由模式1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.routing.queue2}")
    public void routingConsumer2(String message) {
        System.out.println("路由模式2:" + message);
    }

}

8.4.5 启动主程序类

在这里插入图片描述

8.5 通配符模式

8.5.1 编写application.yml

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
# 日志
logging:
  pattern:
    console: '%d{HH:mm:ss.SSS}%clr(%-5level) --- [%-15thread]%cyan(%-50logger{50}):%msg%n'

rabbitmq:
  simple:
    queue: simple_queue
  workqueue:
    queue: work_queue
  pubsub:
    exchange: pub_sub_exchange
    queue1: pub_sub_queue1
    queue2: pub_sub_queue2
  routing:
    exchange: routing_exchange
    queue1: routing_queue1
    queue2: routing_queue2
    routingkey1: info
    routingkey2: error
  topic:
    exchange: topic_exchange
    queue1: topic_queue1
    queue2: topic_queue2
    routingkey1: "*.java.*"
    routingkey2: "#.java.#"

8.5.2 声明队列和交换机

    /**
     * 通配符模式
     */
    @Bean("${rabbitmq.topic.exchange}")
    public Exchange topicExchange(){
        return ExchangeBuilder.topicExchange(environment.getProperty("rabbitmq.topic.exchange")).durable(true).build();
    }

    @Bean("${rabbitmq.topic.queue1}")
    public Queue topicQueue1(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.topic.queue1")).build();
    }

    @Bean("${rabbitmq.topic.queue2}")
    public Queue topicQueue2(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.topic.queue2")).build();
    }

    @Bean
    public Binding bindTopicExchangeQueue1(){
        return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with(environment.getProperty("rabbitmq.topic.routingkey1")).noargs();
    }

    @Bean
    public Binding bindTopicExchangeQueue2(){
        return BindingBuilder.bind(topicQueue2()).to(topicExchange()).with(environment.getProperty("rabbitmq.topic.routingkey2")).noargs();
    }

8.5.3 测试类发送消息

package com.top.psjj.producer;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

@SpringBootTest
public class TopicMessageSendTest {


    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private Environment environment;

    @Test
    public void topicSendMessage(){
        rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.topic.exchange"),"a.b.c.d.java.aaa","通配符消息发送1111111");
    }

    @Test
    public void topicSendMessage2(){
        rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.topic.exchange"),"haha.java.1","^_^通配符消息发送6844");
    }
}

8.5.4 编写消费者application.yml

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
# 日志
logging:
  pattern:
    console: '%d{HH:mm:ss.SSS}%clr(%-5level) --- [%-15thread]%cyan(%-50logger{50}):%msg%n'

rabbitmq:
  simple:
    queue: simple_queue
  workqueue:
    queue: work_queue
  pubsub:
    exchange: pub_sub_exchange
    queue1: pub_sub_queue1
    queue2: pub_sub_queue2
  routing:
    exchange: routing_exchange
    queue1: routing_queue1
    queue2: routing_queue2
    routingkey1: info
    routingkey2: error
  topic:
    exchange: topic_exchange
    queue1: topic_queue1
    queue2: topic_queue2
    routingkey1: "*.java.*"
    routingkey2: "#.java.#"

8.5.5 监听队列信息

package com.top.psjj.consumer.mq.listener;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ConsumerListener {

    @RabbitListener(queues = "${rabbitmq.simple.queue}")
    public void simpleMessageListen(String message){
        System.out.println("简单消息:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue1(String message){
        System.out.println("工作消费任务1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.workqueue.queue}")
    public void workqueue2(String message){
        System.out.println("工作消费任务2:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.pubsub.queue1}")
    public void pubsubConsumer1(String message){
        System.out.println("发布订阅模式1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.pubsub.queue2}")
    public void pubsubConsumer2(String message) {
        System.out.println("发布订阅模式2:" + message);
    }

    @RabbitListener(queues = "${rabbitmq.routing.queue1}")
    public void routingConsumer1(String message){
        System.out.println("路由模式1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.routing.queue2}")
    public void routingConsumer2(String message) {
        System.out.println("路由模式2:" + message);
    }

    @RabbitListener(queues = "${rabbitmq.topic.queue1}")
    public void topicConsumer1(String message){
        System.out.println("通配符模式1:"+ message);
    }

    @RabbitListener(queues = "${rabbitmq.topic.queue2}")
    public void topicConsumer2(String message) {
        System.out.println("通配符模式222:" + message);
    }

}

8.5.6 启动消费者主程序类

在这里插入图片描述

8.6 总结

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

9. RabbitMQ 高级部分

在这里插入图片描述

9.1 消息的可靠性投递

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

9.2 创建项目

9.2.1 导入依赖 POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.top.psjj</groupId>
    <artifactId>rabbitmq-day02</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rabbitmq-day02</name>
    <packaging>pom</packaging>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

9.2.2 创建mq-consumer和mq-producer

9.2.3 给两个模块创建application.yml

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj

9.2.4 给两个模块创建主启动类

package com.top.psjj;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProducerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProducerApplication.class,args);
    }
}

package com.top.psjj;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
}


9.3 消息可靠性投递_确认模式

在这里插入图片描述

9.3.1 消息确认模式,保证消息传递到交换机

在这里插入图片描述

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
    # 消息确认模式,保证消息传递到交换机
    publisher-confirm-type: correlated

9.3.2 生产者定义确认模式的回调方法

9.3.2.1 添加application.yml信息
spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
    # 消息确认模式,保证消息传递到交换机
    publisher-confirm-type: correlated

# 自定义配置
rabbitmq:
  test1:
    exchange: test_exchange
    queue: test_queue
    routing-key: "*.java.*"
   
9.3.2.2 创建配置类,构建交换机,队列和routing-key
package com.top.psjj.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

@Configuration
public class RabbitMQConfiguration {

    @Autowired
    private Environment environment;

    /**
     * 声明交换机,队列和routing-key
     * @return
     */
    @Bean("${rabbitmq.test.exchange}")
    public Exchange getExchange(){
        return ExchangeBuilder.topicExchange(environment.getProperty("rabbitmq.test.exchange")).durable(true).build();
    }

    @Bean("${rabbitmq.test.queue}")
    public Queue getQueue(){
        return QueueBuilder.durable(environment.getProperty("rabbitmq.test.queue")).build();
    }

    @Bean
    public Binding bindingRelation(){
       return BindingBuilder.bind(getQueue()).to(getExchange()).with(environment.getProperty("rabbitmq.test.routing-key")).noargs();
    }
}

9.3.2.3 测试发送消息

在这里插入图片描述

package com.top.psjj;

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;

@SpringBootTest
public class TestSendMessage {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private Environment environment;


    @Test
    public void test1() throws InterruptedException {
        // 确认模式
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             *
             * @param correlationData 相关配置信息
             * @param ack 交换机是否收到了消息
             * @param cause 失败原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (ack){
                    System.out.println("交换机接收到了消息" + correlationData);
                }else{
                    System.out.println("发送失败" +correlationData
                            + "~~~"+ cause);
                }
            }
        });

        // 发送消息给交换机
        rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.test.exchange"),"a.java.b","~~~~~我的消息123123123123");
//        Thread.sleep(2000);
    }
}

在这里插入图片描述
网上查阅了半天没找到解决问题的,后来想了一下,我是在测试方法中进行测试,当测试方法结束,rabbitmq相关的资源也就关闭了,虽然我们的消息发送出去,但异步的ConfirmCallback却由于资源关闭而出现了上面的问题。
所以在测试方法等待一段时间即可
在这里插入图片描述

9.4 退回模式

在这里插入图片描述

9.4.1 开启退回模式在application.yml

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
    # 消息确认模式,保证消息传递到交换机
    publisher-confirm-type: correlated
    # 开始退回模式
    publisher-returns: true

# 自定义配置
rabbitmq:
  test:
    exchange: test_exchange
    queue: test_queue
    routing-key: "*.java.*"

9.4.2 测试结果

  /**
     * 将消息从交换机发送到队列中,如果出现错误会走该方法
     * @throws InterruptedException
     */
    @Test
    public void test2() throws InterruptedException {
        // 退回模式
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                System.out.println("交换机:" + returnedMessage.getExchange());
                System.out.println("消息对象:" + returnedMessage.getMessage());
                System.out.println("错误码:"   + returnedMessage.getReplyCode());
                System.out.println("错误信息:" + returnedMessage.getReplyText());
                System.out.println("路由键:" +returnedMessage.getRoutingKey());

                //TODO 发送失败再次发送
                rabbitTemplate.convertAndSend(returnedMessage.getExchange(),returnedMessage.getRoutingKey(),returnedMessage.getMessage());
            }
        });

        // 发送消息给交换机
        rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.test.exchange"),"a.java12111.11","~~~~~我的消息123123123123");
    }

9.5 ACK模式

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

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
    # 开启ack模式
    listener:
      simple:
        acknowledge-mode: manual

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

package com.top.psjj.listener;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;


@Component
@Slf4j
public class RabbitMQListener {

    @RabbitListener(queues = "test_queue")
    public void listenMessage(Message message, Channel channel) throws IOException, InterruptedException {

        // 消息投递序号,消息每次投递该数值都会加1
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        try {
            int i = 1 / 0; // 模拟处理消息出现bug
            // 成功接受消息
            System.out.println(new String(message.getBody()));
            // 消费消息成功
            /**
             * 1.消息投递序号
             * 2.是否一次性牵手多条消息
             */
            channel.basicAck(deliveryTag, true);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("消息签收失败:" + e.getMessage(), e);
            Thread.sleep(2000);
            /**
             * 拒签消息
             * 1.消息投递序号
             * 2.是否一次签收多条消息
             * 3.拒签后消息是否重回队列
             */
            channel.basicNack(deliveryTag,true,true);
        }


    }
}

启动消费者主程序类
在这里插入图片描述

10. RabbitMQ高级特性

10.1 消费限流

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
生产者发送消息
在这里插入图片描述
在这里插入图片描述
消费者接受消息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

10.2 消息不公平分发

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

10.3 队列所有消息存活时间

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

10.4 单条消息存活时间

在这里插入图片描述

10.5 优先级队列

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结论: 优先级高的先执行

11. RabbitMQ 死信队列

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

死心队列实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、定义死信队列

spring:
  rabbitmq:
    host: 101.227.52.230
    port: 5672
    virtual-host: /cj
    username: cj
    password: cj
    # 消息确认模式,保证消息传递到交换机
    publisher-confirm-type: correlated
    # 开始退回模式
    publisher-returns: true
    # ack模式
    listener:
      simple:
        acknowledge-mode: manual


# 自定义配置
rabbitmq:
  test:
    exchange: test_exchange
    queue: test_queue
    routing-key: "*.java.*"
  dead:
    exchange: dead_exchange
    queue: dead_queue
    routing-key: "#.dead.#"

2、配置死信交换机,队列并绑定关系

package com.top.psjj.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

@Configuration
public class RabbitMQConfiguration {

    @Autowired
    private Environment environment;

    /**
     * 声明交换机,队列和routing-key
     * @return
     */
    @Bean("${rabbitmq.test.exchange}")
    public Exchange getExchange(){
        return ExchangeBuilder.topicExchange(environment.getProperty("rabbitmq.test.exchange")).durable(true).build();
    }

    @Bean("${rabbitmq.test.queue}")
    public Queue getQueue(){
        return QueueBuilder
                .durable(environment.getProperty("rabbitmq.test.queue"))
                //设置所有消息存活时间
//                .ttl(10000)
                // 设置最大优先级
//                .maxPriority(10)
                .deadLetterExchange(environment.getProperty("rabbitmq.dead.exchange"))
                .deadLetterRoutingKey("a.dead.b")
                .build();
    }

    @Bean
    public Binding bindingRelation(){
       return BindingBuilder.bind(getQueue()).to(getExchange()).with(environment.getProperty("rabbitmq.test.routing-key")).noargs();
    }


    /**
     * 声明死信交换机,死信队列和死信routing-key
     * @return
     */
    @Bean("${rabbitmq.dead.exchange}")
    public Exchange deadExchange(){
        return ExchangeBuilder.topicExchange(environment.getProperty("rabbitmq.dead.exchange")).durable(true).build();
    }

    @Bean("${rabbitmq.dead.queue}")
    public Queue deadQueue(){
        return QueueBuilder
                .durable(environment.getProperty("rabbitmq.dead.queue"))
                //设置所有消息存活时间
//                .ttl(10000)
                // 设置最大优先级
//                .maxPriority(10)
                .build();
    }

    @Bean
    public Binding bindingDeadRelation(){
        return BindingBuilder.bind(deadQueue()).to(deadExchange()).with(environment.getProperty("rabbitmq.dead.routing-key")).noargs();
    }
}

  @Test
    public void test8(){

            MessageProperties messageProperties = new MessageProperties();
            messageProperties.setExpiration("5000");
            Message message = new Message(("正常队列内容:").getBytes(),messageProperties);
            rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.test.exchange"), "a.java.1",message);
    }

测试消息只能发送10条,剩下的消息加入死信队列


// 最大发送10条信息
// .maxLength(10)

  // 测试只能发送10条信息,超出的消息都存入死信队列
    @Test
    public void test9(){
        for (int i = 0; i < 100; i++) {
            String message = "aaaa" + i;
            rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.test.exchange"), "a.java.1",message);
        }
    }

添加消息的存活时间,时间过期就加入死信队列

//设置所有消息存活时间
                .ttl(10000)
                 // 测试队列过期时间到了,加入死信对垒
    @Test
    public void test10(){
            rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.test.exchange"), "a.java.1","队列过期");
    }
}

测试消息拒签,成为死信队列

   // 测试消息拒签,成为死信队列
    @Test
    public void test11(){
        for (int i = 0; i <=5; i++) {
            String message = "牵手消息发送~~~~~" + i;
            rabbitTemplate.convertAndSend(environment.getProperty("rabbitmq.test.exchange"), "a.java.1",message);
        }
    }
  @RabbitListener(queues = "test_queue")
    public void listenMessageCommon(Message message, Channel channel) throws IOException, InterruptedException {
        // 消息投递序号,消息每次投递该数值都会加1
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 1.成功接受消息
            System.out.println("消息拒签:" + new String(message.getBody()) + "失败");

            // 3.签收消息
            /**
             * 1.消息投递序号
             * 2.是否一次性牵手多条消息
             * 3.拒签
             */
            channel.basicNack(deliveryTag, true,false);
        } catch (Exception e) {
        }
    }

12. 延迟队列

在这里插入图片描述

12.1 死信队列的实现

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、创建主程序类
2、创建application.yml
3、配置交换机,队列和绑定关系

package com.top.psjj.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 编写交换机,队列和两者的绑定关系
 */
@Configuration
public class OrderConfiguration {

    /**
     * 配置订单交换机,队列和绑定关系
     * @return
     */
    @Bean("order-exchange")
    public Exchange orderExchange(){
        return ExchangeBuilder.topicExchange("order-exchange").durable(true).build();
    }

    @Bean("order-queue")
    public Queue orderQueue(){
        return QueueBuilder
                .durable("order-queue")
                // 队列过期时间
                .ttl(10000)
                // 配置死信队列交换机
                .deadLetterExchange("dead-exchange")
                // 配置死信队列Routing-key
                .deadLetterRoutingKey("dead.pay")
                .build();
    }

    @Bean
    public Binding bindExchangeQueue(){
        return BindingBuilder.bind(orderQueue()).to(orderExchange()).with("*.pay.*").noargs();
    }


    @Bean("dead-exchange")
    public Exchange deadExchange(){
        return ExchangeBuilder.topicExchange("dead-exchange").durable(true).build();
    }

    @Bean("dead-queue")
    public Queue deadQueue(){
        return QueueBuilder.durable("dead-queue").build();
    }

    @Bean
    public Binding deadBind(){
        return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("#.pay").noargs();
    }

}

4、发送消息

package com.top.psjj.controller;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
public class OrderController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 创建订单
     */
    @RequestMapping("/create")
    public String create(){
        // 1、生成订单编号
        String orderId = UUID.randomUUID().toString();
        // 2、插入数据库
        System.out.println("将订单插入数据库" + orderId);
        // 3、将订单编号发送到订单队列中,如果10s未完成支付,将取消该订单
        rabbitTemplate.convertAndSend("order-exchange","order.pay.1","发送订单消息");
        return "下单成功,请及时支付";
    }
}

5、监听队列信息

package com.top.psjj.listen;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * 用来监听死信队列
 */
@Component
@Slf4j
public class OrderListen {

    @RabbitListener(queues = "dead-queue")
    public void orderListen(String orderId){
        if (!StringUtils.isEmpty(orderId)){
            log.info("查看订单状态");
            log.info("如果订单已经支付,无需处理");
            log.info("订单未支付,则取消订单信息");
        }
    }
}

6、测试结果
在这里插入图片描述

12、延迟队列插件

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

12.1 插件

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

在这里插入图片描述

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

12.2 延迟队列实现

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

12.2.2 配置延迟队列

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

12.2.3 集群部署

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

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

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

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值