引入pom依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-amqpartifactId>
dependency>
设置application.yml配置文件
spring:
rabbitmq:
host: 127.0.0.1
port: 7006
username: admin
password: admin
# 是否触发回调方法
# NONE值是禁用发布确认模式,是默认值
# CORRELATED值是发布消息成功到交换器后会触发回调方法,如1示例
# SIMPLE值经测试有两种效果,其一效果和CORRELATED值一样会触发回调方法,其二在发布消息成功后使用rabbitTemplate调用waitForConfirms或waitForConfirmsOrDie方法等待broker节点返回发送结果,根据返回结果来判定下一步的逻辑,要注意的点是waitForConfirmsOrDie方法如果返回false则会关闭channel,则接下来无法发送消息到broker;
publisher-confirm-type: correlated
package com.rabbmq.config;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 简单模式
*
* @author He PanFu
* @date 2021-09-16 12:33:25
*/
@Configuration
public class RabbitSimpleConfig {
@Bean
public Queue simpleQueueWx() {
// 队列名称,是否持久化
return new Queue("simple_queue", true);
}
}
@Autowired
RabbitTemplate rabbitTemplate;
@GetMapping("/simple")
public String sendSimpleMessage() {
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("simple_queue", getStringObjectMap());
}
return "ok";
}
private Map<String, Object> getStringObjectMap() {
String messageId = String.valueOf(UUID.randomUUID());
String messageData = "test message, hello!";
String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Map<String, Object> map = new HashMap<>();
map.put("messageId", messageId);
map.put("messageData", messageData);
map.put("createTime", createTime);
return map;
}
package com.rabbitmq.receiver;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 简单模式:微信订阅
*
* @author He PanFu
* @date 2021-09-16 12:47:32
*/
@Component
@RabbitListener(queues = "simple_queue")
public class RabbitSimpleWXListener {
@RabbitHandler
public void init(Map testMessage) {
System.out.println("简单模式(微信):" + testMessage);
}
}
备注:
package com.cyun.demo.rabbitmq.provider;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* 工作模式
*
* @author He PanFu
* @date 2021-09-16 12:33:25
*/
@Component
public class RabbitWorkManage {
/**
* 工作队列
*
* @return 队列
*/
@Bean
public Queue workQueue() {
return new Queue("work_queue", true);
}
}
@GetMapping("/work")
public String sendWorkMessage() {
for (int i = 0; i < 10; i++) {
rabbitTemplate.convertAndSend("work_queue", getStringObjectMap());
}
return "ok";
}
备注:正式环境是启动多台消费服务,我这里直接简单化模拟。
package com.cyun.demo.rabbitmq.consumer;
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;
import java.util.concurrent.TimeUnit;
/**
* 工作模式:队列监听
*
* @author He PanFu
* @date 2021-09-16 12:47:32
*/
@Slf4j
@Component
public class RabbitWorkListener {
@RabbitListener(queues = "work_queue")
public void messageListener1(Object msg, Channel channel, Message message) throws InterruptedException, IOException {
TimeUnit.SECONDS.sleep(1);
log.info("1消息处理完成,消息内容:{}", msg);
}
@RabbitListener(queues = "work_queue")
public void messageListener2(Object msg, Channel channel, Message message) throws IOException, InterruptedException {
TimeUnit.SECONDS.sleep(2);
log.info("2消息处理完成,消息内容:{}", msg);
}
}
开启手动ack,并且每次只能读取1条消息
spring:
rabbitmq:
host: 127.0.0.1
port: 7006
username: admin
password: admin
# 是否触发回调方法
# NONE值是禁用发布确认模式,是默认值
# CORRELATED值是发布消息成功到交换器后会触发回调方法,如1示例
# SIMPLE值经测试有两种效果,其一效果和CORRELATED值一样会触发回调方法,其二在发布消息成功后使用rabbitTemplate调用waitForConfirms或waitForConfirmsOrDie方法等待broker节点返回发送结果,根据返回结果来判定下一步的逻辑,要注意的点是waitForConfirmsOrDie方法如果返回false则会关闭channel,则接下来无法发送消息到broker;
publisher-confirm-type: correlated
listener:
simple:
# 开启手动确定
acknowledge-mode: manual
# 预处理模式更改为每次读取1条消息,在消费者未回执确认之前,不在进行下一条消息的投送
prefetch: 1
package com.cyun.demo.rabbitmq.consumer;
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;
import java.util.concurrent.TimeUnit;
/**
* 工作模式:队列监听
*
* @author He PanFu
* @date 2021-09-16 12:47:32
*/
@Slf4j
@Component
public class RabbitWorkListener {
@RabbitListener(queues = "work_queue")
public void messageListener1(Object msg, Channel channel, Message message) throws InterruptedException, IOException {
log.info("1消息开始处理,消息内容:{}", msg);
// 公平分发:手动进行确认消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
// 手动返回未确认消息,requeue 为true时,重新入队
// channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
}
@RabbitListener(queues = "work_queue")
public void messageListener2(Object msg, Channel channel, Message message) throws IOException, InterruptedException {
log.info("2消息开始处理,消息内容:{}", msg);
TimeUnit.SECONDS.sleep(1);
// 公平分发:手动进行确认消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
package com.cyun.demo.rabbitmq.provider;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 发布/订阅模式
*
* @author He PanFu
* @date 2022-04-16 17:04:55
*/
@Configuration
public class RabbitmqFanoutConfig {
/**
* 设置交换机:
*
* durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
* exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
* autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
*
* @return 发布/订阅交换机
*/
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange("fanout_exchange", true, false);
}
/**
* 微信队列
*
* @return 队列
*/
@Bean
public Queue fanoutQueueWx() {
return new Queue("fanout_queue_wx", true);
}
/**
* 短信队列
*
* @return 队列
*/
@Bean
public Queue fanoutQueueDx() {
return new Queue("fanout_queue_dx", true);
}
/**
* 微信队列绑定交换机
*
* @return 绑定对象
*/
@Bean
public Binding fanoutBindingWx() {
return BindingBuilder.bind(fanoutQueueWx()).to(fanoutExchange());
}
/**
* 短信队列绑定交换机
*
* @return 绑定对象
*/
@Bean
public Binding fanoutBindingDx() {
return BindingBuilder.bind(fanoutQueueDx()).to(fanoutExchange());
}
}
@GetMapping("/fanout")
public String sendFanoutMessage() {
for (int i = 0; i < 10; i++) {
//将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
rabbitTemplate.convertAndSend("fanout_exchange", "", getStringObjectMap(), new CorrelationData(UUID.randomUUID().toString()));
}
return "ok";
}
package com.cyun.demo.rabbitmq.consumer;
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.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* 发布/订阅模式:队列监听
*
* @author He PanFu
* @date 2021-09-16 12:47:32
*/
@Slf4j
@Component
public class RabbitmqFanoutListener {
@RabbitListener(queues = "fanout_queue_wx")
public void messageListener1(Object msg, Channel channel, Message message, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws InterruptedException, IOException {
log.info("订阅模式(微信),消息开始处理,消息内容:{}", msg);
// 手动进行确认消息
channel.basicAck(tag, false);
}
@RabbitListener(queues = "fanout_queue_dx")
public void messageListener2(Object msg, Channel channel, Message message) throws IOException, InterruptedException {
log.info("订阅模式(短信),消息开始处理,消息内容:{}", msg);
// 手动进行确认消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
package com.cyun.demo.rabbitmq.provider;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* @author He PanFu
* @date 2022-04-16 18:29:03
*/
@Configuration
public class RabbitmqDirectConfig {
/**
* 设置交换机:
*
* durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
* exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
* autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
*
* @return 交换机:
*/
@Bean
public DirectExchange directExchange() {
return new DirectExchange("direct_exchange", true, false);
}
/**
* 微信队列
*
* @return 队列
*/
@Bean
public Queue directQueueWx() {
return new Queue("direct_queue_wx", true);
}
/**
* 短信队列
*
* @return 队列
*/
@Bean
public Queue directQueueDx() {
return new Queue("direct_queue_dx", true);
}
/**
* 微信队列绑定交换机
*
* @return 绑定
*/
@Bean
public Binding directBindingWx() {
return BindingBuilder.bind(directQueueWx()).to(directExchange()).with("wx");
}
/**
* 短信队列绑定交换机
*
* @return 绑定
*/
@Bean
public Binding directBindingDx() {
return BindingBuilder.bind(directQueueDx()).to(directExchange()).with("dx");
}
}
@GetMapping("/direct/{routingKey}")
public String sendDirectMessage(@PathVariable("routingKey") String routingKey) {
rabbitTemplate.convertAndSend("direct_exchange", routingKey, getStringObjectMap());
return "ok";
}
package com.cyun.demo.rabbitmq.consumer;
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.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.io.IOException;
/**
* 路由模式
*
* @author He PanFu
* @date 2022-04-16 18:32:19
*/
@Slf4j
@Component
public class RabbitmqDirectListener {
@RabbitListener(queues = "direct_queue_wx")
public void messageListener1(Object msg, Channel channel, Message message, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws InterruptedException, IOException {
log.info("订阅模式(微信),消息开始处理,消息内容:{}", msg);
// 手动进行确认消息
channel.basicAck(tag, false);
}
@RabbitListener(queues = "direct_queue_dx")
public void messageListener2(Object msg, Channel channel, Message message) throws IOException, InterruptedException {
log.info("订阅模式(短信),消息开始处理,消息内容:{}", msg);
// 手动进行确认消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
package com.cyun.demo.rabbitmq.provider;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 主题模式
*
* @author He PanFu
* @date 2022-04-18 09:00:43
*/
@Configuration
public class RabbitmqTopicConfig {
/**
* 设置交换机:
*
* durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
* exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
* autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
*
* @return 交换机
*/
@Bean
public TopicExchange topicExchange() {
return new TopicExchange("topic_exchange", true, false);
}
/**
* 设置微信队列
*
* @return 队列
*/
@Bean
public Queue topicQueueWx() {
return new Queue("topic_queue_wx", true);
}
/**
* 设置短信队列
*
* @return 队列
*/
@Bean
public Queue topicQueueDx() {
return new Queue("topic_queue_dx", true);
}
/**
* 进行微信队列绑定交换机
* "*" 表示任何一个词
* "#" 表示0或1个词
*
* @return 绑定
*/
@Bean
public Binding topicBindingWx() {
return BindingBuilder.bind(topicQueueWx()).to(topicExchange()).with("#.wx.#");
}
/**
* 进行短信队列绑定交换机
* "*" 表示任何一个词
* "#" 表示0或1个词
*
* @return 绑定
*/
@Bean
public Binding topicBindingDx() {
return BindingBuilder.bind(topicQueueDx()).to(topicExchange()).with("dx.*");
}
}
@GetMapping("/topic")
public String sendTopicMessage() {
String messageId = String.valueOf(UUID.randomUUID());
String messageData = "test message, hello!";
String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Map<String, Object> map = new HashMap<>();
map.put("messageId", messageId);
map.put("messageData", messageData);
map.put("createTime", createTime);
//将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
map.put("key", "wx");
rabbitTemplate.convertAndSend("topic_exchange", "wx", map);
map.put("key", "wx.www");
rabbitTemplate.convertAndSend("topic_exchange", "wx.www", map);
map.put("key", "wx.www.www");
rabbitTemplate.convertAndSend("topic_exchange", "wx.www.www", map);
map.put("key", "dx");
rabbitTemplate.convertAndSend("topic_exchange", "dx", map);
map.put("key", "dx.www");
rabbitTemplate.convertAndSend("topic_exchange", "dx.www", map);
map.put("key", "dx.www.www");
rabbitTemplate.convertAndSend("topic_exchange", "dx.www.www", map);
return "ok";
}
package com.cyun.demo.rabbitmq.consumer;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
/**
* 主题模式
*
* @author He PanFu
* @date 2022-04-18 09:18:47
*/
@Slf4j
@Component
public class RabbitmqTopicListener {
/**
* 微信队列监听
*
* @param testMessage 数据
*/
@RabbitListener(queues = "topic_queue_wx")
public void messageListener2(Map testMessage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
log.info("主题模式(微信),key:{},testMessage:{}", testMessage.get("key"),testMessage);
channel.basicAck(tag, false);
}
/**
* 短信队列监听
*
* @param testMessage 数据
*/
@RabbitListener(queues = "topic_queue_dx")
public void messageListener1(Map testMessage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
log.info("主题模式(短信),key:{},testMessage:{}", testMessage.get("key"),testMessage);
channel.basicAck(tag, false);
}
}
package com.cyun.demo.rabbitmq.provider;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.HeadersExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* 参数模式
*
* @author He PanFu
* @date 2022-04-18 09:53:43
*/
@Configuration
public class RabbitmqHeadersConfig {
/**
* 设置交换机:
*
* durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
* exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
* autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
*
* @return 交换机
*/
@Bean
public HeadersExchange headersExchange() {
return new HeadersExchange("headers_exchange", true, false);
}
/**
* 设置微信队列
*
* @return 队列
*/
@Bean
public Queue headersQueueWx() {
return new Queue("headers_queue_wx", true);
}
/**
* 设置短信队列
*
* @return 队列
*/
@Bean
public Queue headersQueueDx() {
return new Queue("headers_queue_dx", true);
}
/**
* 设置邮箱队列
*
* @return 队列
*/
@Bean
public Queue headersQueueYx() {
return new Queue("headers_queue_yx", true);
}
/**
* 进行微信队列绑定交换机,请求头中包含两个
*
* @return 绑定
*/
@Bean
public Binding headersBindingWx() {
Map<String, Object> map = new HashMap<>();
map.put("One", "A");
map.put("Two", "B");
return BindingBuilder.bind(headersQueueWx()).to(headersExchange()).whereAll(map).match();
}
/**
* 进行短信队列绑定交换机,请求头中包含任意一个
*
* @return 绑定
*/
@Bean
public Binding headersBindingDx() {
Map<String, Object> map = new HashMap<>();
map.put("One", "A");
map.put("Two", "B");
return BindingBuilder.bind(headersQueueDx()).to(headersExchange()).whereAny(map).match();
}
/**
* 进行邮箱队列绑定交换机
*
* @return 绑定
*/
@Bean
public Binding headersBindingYx() {
return BindingBuilder.bind(headersQueueYx()).to(headersExchange()).where("Three").matches("C");
}
}
@GetMapping("/topic")
public String sendTopicMessage() {
String messageId = String.valueOf(UUID.randomUUID());
String messageData = "test message, hello!";
String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Map<String, Object> map = new HashMap<>();
map.put("messageId", messageId);
map.put("messageData", messageData);
map.put("createTime", createTime);
//将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
map.put("key", "wx");
rabbitTemplate.convertAndSend("topic_exchange", "wx", map);
map.put("key", "wx.www");
rabbitTemplate.convertAndSend("topic_exchange", "wx.www", map);
map.put("key", "wx.www.www");
rabbitTemplate.convertAndSend("topic_exchange", "wx.www.www", map);
map.put("key", "dx");
rabbitTemplate.convertAndSend("topic_exchange", "dx", map);
map.put("key", "dx.www");
rabbitTemplate.convertAndSend("topic_exchange", "dx.www", map);
map.put("key", "dx.www.www");
rabbitTemplate.convertAndSend("topic_exchange", "dx.www.www", map);
return "ok";
}
package com.cyun.demo.rabbitmq.consumer;
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.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Map;
/**
* 参数模式
*
* @author He PanFu
* @date 2022-04-18 10:27:15
*/
@Slf4j
@Component
public class RabbitmqHeadersListener {
/**
* 微信队列监听
*
* @param testMessage 数据
*/
@RabbitListener(queues = "headers_queue_wx")
public void messageListener1(Message testMessage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
log.info("参数模式(微信),testMessage:{}", testMessage);
channel.basicAck(tag, false);
}
/**
* 短信队列监听
*
* @param testMessage 数据
*/
@RabbitListener(queues = "headers_queue_dx")
public void messageListener2(Message testMessage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
log.info("参数模式(短信),testMessage:{}", testMessage);
channel.basicAck(tag, false);
}
/**
* 邮箱队列监听
*
* @param testMessage 数据
*/
@RabbitListener(queues = "headers_queue_yx")
public void messageListener3(Message testMessage, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
log.info("参数模式(邮箱),testMessage:{}", testMessage);
channel.basicAck(tag, false);
}
}
介绍:“死信”是RabbitMQ中的一种消息机制,当你在消费消息时,如果队列里的消息出现以下情况,那么该消息将成为“死信”。
“死信”消息会被RabbitMQ进行特殊处理,如果配置了死信队列信息,那么该消息将会被丢进死信队列中,如果没有配置,则该消息将会被丢弃。
注意:如果修改了队列的配置信息,需重新删除原有的队列重新注册。
package com.cyun.demo.rabbitmq.provider;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* 发布/订阅模式
*
* @author He PanFu
* @date 2022-04-16 17:04:55
*/
@Configuration
public class RabbitmqFanoutTtlConfig {
/**
* 设置交换机:
*
* durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
* exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
* autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
*
* @return 发布/订阅交换机
*/
@Bean
public FanoutExchange fanoutTtlExchange() {
return new FanoutExchange("fanout_ttl_exchange", true, false);
}
/**
* 微信队列
*
* @return 队列
*/
@Bean
public Queue fanoutTtlQueueWx() {
Map<String, Object> map = new HashMap<>();
// 过期时间
map.put("x-message-ttl", 1000);
// 死信队列,消息过期后,会放到死信交换机中
map.put("x-dead-letter-exchange", "direct_exchange");
map.put("x-dead-letter-routing-key", "wx");
return new Queue("fanout_ttl_queue_wx", true, false, false, map);
}
/**
* 微信队列绑定交换机
*
* @return 绑定对象
*/
@Bean
public Binding fanoutTtlBindingWx() {
return BindingBuilder.bind(fanoutTtlQueueWx()).to(fanoutTtlExchange());
}
}
@GetMapping("/fanout/ttl")
public String sendFanoutTtlMessage() {
rabbitTemplate.convertAndSend("fanout_ttl_exchange", "", getStringObjectMap());
return "ok";
}
package com.cyun.demo.rabbitmq.consumer;
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.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* 发布/订阅模式:队列监听
*
* @author He PanFu
* @date 2021-09-16 12:47:32
*/
@Slf4j
@Component
public class RabbitmqFanoutTtlListener {
@RabbitListener(queues = "fanout_ttl_queue_wx")
public void messageListener1(Object msg, Channel channel, Message message, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws InterruptedException, IOException {
log.info("订阅模式TTL(微信),消息开始处理,消息内容:{}", msg);
// 触发情况一:消息被否定确定。multiple:是否批量处理.true:将一次性ack所有小于deliveryTag的消息,requeue:为true时,重新入队
// channel.basicNack(tag,false,false);
// 触发情况二:超时
TimeUnit.SECONDS.sleep(15);
channel.basicAck(tag, false);
}
}
注意:两个过期时间,以最小准。
@GetMapping("/fanout/ttl/5000")
public String sendFanoutTTLMessageMessage() {
// 设置过期时间
MessagePostProcessor processor = message -> {
message.getMessageProperties().setExpiration("5000");
message.getMessageProperties().setContentEncoding("UTF-8");
return message;
};
rabbitTemplate.convertAndSend("fanout_ttl_exchange", "", getStringObjectMap(), processor);
return "ok";
}
具体步骤为:注册(注册交换机 -> 注册队列 -> 绑定交换机与队列) -> 监听 -> 加入队列