1.依赖引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId><version>2.3.12.RELEASE</version>
</dependency>
2.配置文件
spring:
rabbitmq:
host: 192.168.2.17
port: 5672
username: admin
password: adminpublisher-confirm-type: correlated
3.死信队列配置类
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class TtlConfig {
public static final String dead_exchange = "deadExchange";
public static final String dead_queue = "deadQueue";
public static final String dead_key = "deadKey";
public static final String normal_exchange = "normalExchange";
String normal_queue = "normalQueue";
String normal_key = "normalKey";
@Bean("deadQueue")
public Queue deadQueue()
{
Queue queue = new Queue(dead_queue, false, false, false, null);
return queue;
}
@Bean("deadExchange")
public DirectExchange deadExchange()
{
DirectExchange exchange = new DirectExchange(dead_exchange, false, false);
return exchange;
}
@Bean("deadBinding")
public Binding deadBinding(@Qualifier("deadQueue") Queue queue,
@Qualifier("deadExchange") DirectExchange exchange)
{
Binding binding = BindingBuilder.bind(queue).to(exchange).with(dead_key);
return binding;
}
@Bean("normalQueue")
public Queue normalQueue()
{
Map<String, Object> params = new HashMap<>();
//正常队列设置死信交换机 参数 key 是固定值
params.put("x-dead-letter-exchange", dead_exchange);
//正常队列设置死信 routing-key 参数 key 是固定值
params.put("x-dead-letter-routing-key", dead_key);
params.put("x-max-length", 6); //最大长度
params.put("x-message-ttl", 5000); // 毫秒单位, 这种是在队列时限制延迟时间
Queue queue = new Queue(normal_queue, false, false, false, params);
return queue;
}
@Bean("normalExchange")
public DirectExchange normalExchange()
{
DirectExchange exchange = new DirectExchange(normal_exchange, false, false);
return exchange;
}
@Bean("normalBinding")
public Binding normalBinding(@Qualifier("normalQueue") Queue queue,
@Qualifier("normalExchange") DirectExchange exchange)
{
Binding binding = BindingBuilder.bind(queue).to(exchange).with(normal_key);
return binding;
}
}
4.消费者
4.1 自动消费
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ClusterConsumer {
@RabbitListener(queues = ClusterConfig.queueName)
public void receiveMsg(Message message)
{
String msg = new String(message.getBody());
log.info("[ClusterConsumer] 收到消息:{}", msg);
}
}
4.2 手动消费
1) 监听
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;
@Component
public class DeadQueueAwareConsumer implements ChannelAwareMessageListener {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
long deliveryTag = message.getMessageProperties().getDeliveryTag();
channel.basicAck(deliveryTag, false);
System.out.println("DeadQueueAwareConsumer->" + deliveryTag);
//basicNack
}
}
2) 工厂
import com.demo.mq.config.TtlConfig;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DeadQueueAwareListenerConfig {
@Autowired
private DeadQueueAwareConsumer deadQueueAwareConsumer;
@Autowired
private CachingConnectionFactory connectionFactory;
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer()
{
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setConcurrentConsumers(1);
container.setMaxConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // RabbitMQ默认是自动确认,这里改为手动确认消
container.setQueueNames(TtlConfig.dead_queue);
container.setMessageListener(this.deadQueueAwareConsumer);
return container;
}
}
3)
5.生产者
5.1 异步类
import com.demo.mq.config.TtlConfig;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class MessageProducer implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
private Integer id = 0;
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init()
{
/**
* true:
* 交换机无法将消息进行路由时,会将该消息返回给生产者
* false:
* 如果发现消息无法进行路由,则直接丢弃
*/
this.rabbitTemplate.setMandatory(true);
this.rabbitTemplate.setConfirmCallback(this);
this.rabbitTemplate.setReturnCallback(this);
}
/**
* 交换机不管是否收到消息的一个回调方法
* CorrelationData
* 消息相关数据
* ack
* 交换机是否收到消息
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
String msg = "";
String id = correlationData != null ? correlationData.getId() : "";
if (ack) {
msg = "交换机已经收到 id 为:" + id + "的消息";
} else {
msg = "交换机还未收到 id 为:" + id + "消息,由于原因: " + cause;
}
System.out.println(msg);
}
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
String msg = "消 息 "+new String(message.getBody())+ ", 被 交 换 机 "+exchange+ "退 回 , 退 回 原 因 :"+replyText+", 路 由 key:" + routingKey;
System.out.println(msg);
}
public void sendMessage(String message) {
CorrelationData correlationData = new CorrelationData();
correlationData.setId(this.id.toString());
rabbitTemplate.convertAndSend(TtlConfig.normal_exchange, "normalKey", message,correlationData);
this.id++;
}
}
5.2 使用
@RestController
@RequestMapping("producer")
public class ProducerController {
@Autowired
private MessageProducer myCallBack;
@GetMapping("ttl/{id}")
public void ttl(@PathVariable("id") String id){
this.myCallBack.sendMessage("info" + id);
}
}
6.测试