简单来说就是消息先发送至一般队列中,不监听一般队列中的消息。等待设置的延迟时间过后,消息由一般队列发送至死信队列,监听死信队列接收消息,完成消息延迟。
1.声明绑定一般队列和交换机,死信队列和交换机(配置文件中做rabbit配置)
@Configuration
public class MqConfig {
@Bean
public Queue ttlQueue() {
Map<String,Object> map = new HashMap<>(1);
//延迟时间
map.put("x-message-ttl", 1000*10);
// 设置消息成为死信后,传发到的路由器
map.put("x-dead-letter-exchange","dead.direct.exchange");
map.put("x-dead-letter-routing-key", "dead");
return new Queue("ttl.queue", true, false, false, map);
}
@Bean
public DirectExchange ttlDirectExchange() {
return new DirectExchange("ttl.direct.exchange", true, false);
}
@Bean
public Binding ttlDirectBinding() {
return BindingBuilder
.bind(ttlQueue())
.to(ttlDirectExchange())
.with("ttl");
}
// =======================以下为死信队列相关配置=========================
@Bean
public Queue deadQueue() {
return new Queue("dead.queue", true);
}
@Bean
public DirectExchange deadDirectExchange() {
return new DirectExchange("dead.direct.exchange", true, false);
}
@Bean
public Binding deadDirectBinding() {
return BindingBuilder
.bind(deadQueue())
.to(deadDirectExchange())
.with("dead");
}
}
2.消息生产者发送消息
rabbitTemplate.convertAndSend("ttl.direct.exchange","ttl",order.getId());
3.消息消费者监听消息
@RabbitListener(queues = "dead.queue")
public void deadQueue(Long orderId) {
//以下为业务内容
Order order = orderService.getById(orderId);
if (order.getStatus() == 1) {
log.info("超时未支付,取消订单");
LambdaQueryWrapper<OrderDetail> qw = new LambdaQueryWrapper<>();
qw.eq(OrderDetail::getOrderId, orderId);
OrderDetail detail = orderDetailMapper.selectOne(qw);
Integer num = detail.getNum();//商品购买数量
order.setStatus(5);
orderService.updateById(order);//修改订单状态
itemClient.updateStock(orderId, num, false);//恢复商品库存
}
}