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 集群部署