常见的使用场景:外卖或电商类平台中用户下单却不打算支付的时候,订单会进入到计时,直至一段时间后自动取消订单。还有等等的其他场景
本次应用与上述场景
引入依赖,配置号yml中的配置后
准备
配置队列和交换机
@Slf4j
@Configuration
public class RabbitMQConfig {
//交换机
public static final String DELAYED_EXCHANGE_NAME = "delayed.exchange";
//队列
public static final String DELAYED_QUEUE_NAME = "delayed.queue";
//routingKey
public static final String DELAYED_ROUTING_KEY = "delayed.routingKey";
//队列
@Bean
public Queue delayedQueue(){
return new Queue(DELAYED_QUEUE_NAME);
}
//交换机
@Bean
public CustomExchange delayedExchange(){
Map<String,Object> arguments = new HashMap<>();
arguments.put("x-delayed-type","direct");
/*
1.交换机名称
2.交换机类型
3.是否持久化
4.是否自动删除
5.其他参数
*/
return new CustomExchange(DELAYED_EXCHANGE_NAME,"x-delayed-message",
true,false,arguments);
}
//绑定
@Bean
public Binding delayedQueueBindingExchange(@Qualifier("delayedQueue") Queue delayedQueue,
@Qualifier("delayedExchange") CustomExchange delayedExchange){
return BindingBuilder.bind(delayedQueue).to(delayedExchange).with(DELAYED_ROUTING_KEY).noargs();
//自定义的交换机需要加.noargs()
}
}
写下发送消息的类
@Service
@Slf4j
public class MQSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMsg(String message, Integer delayTime){
log.info("当前时间:{},发送时长{}毫秒的信息给延迟队列delayed.queue:{}",
new Date().toString(),delayTime,message);
rabbitTemplate.convertAndSend(RabbitMQConfig.DELAYED_EXCHANGE_NAME,
RabbitMQConfig.DELAYED_ROUTING_KEY,message, message1 -> {
//发送延迟消息 延迟时长 ms
message1.getMessageProperties().setDelay(delayTime);
return message1;
});
}
}
消费者中涉及功能先不写,暂时先这样
@Slf4j
@Component
public class DelayQueueConsumer {
//开始监控
@RabbitListener(queues = DelayedQueueConfig.DELAYED_QUEUE_NAME)
public void receiveDelayQueue(Message message){
String msg = new String(message.getBody());
log.info("当前时间:{},收到延迟队列消息:{}",new Date().toString(),msg);
}
}
结合需要的功能
用户未支付的请求发发过来,我们同时去将订单的编号作为消息发送
/**
* 用户下单但是没有支付
*
* @param orders
* @return
*/
@PostMapping("/submit1")
public Result<String> submit1(@RequestBody Orders orders){
log.info("取消支付订单--{}",orders);
Long submitId = ordersService.submit(orders, 1);
String id = ""+submitId;
mqSender.sendMsg(id,10000);//把订单号的信息发送
return Result.success("取消成功");
}
往消费者中增添功能,固定时间后消费者就会接收到队列,从而去处理
@Component
@Slf4j
public class MQReceiver {
@Autowired
private OrdersService ordersService;
@RabbitListener(queues = RabbitMQConfig.DELAYED_QUEUE_NAME)
public void receive(Message message){
//接受到订单号的信息的话就对比订单的支付情况 删掉
String msg = new String(message.getBody());
log.info("当前时间:{},收到延迟队列消息:{}",new Date().toString(),msg);
BigInteger id = new BigInteger(msg);
Orders byId = ordersService.getById(id);
Integer status = byId.getStatus();
if(status==1){
byId.setStatus(5);
ordersService.updateById(byId);
log.info("超时已经取消订单:{}",id);
}
}
}
就成功的完成了。
总结
很多东西都是看起来简单做起来难,刚学完一个技术的时候,有时候不知道怎么去应用,感觉毫无头绪,无从下手,也不知道实际的情况下到底是怎么应用的。但是当我们克服这些困难之后,从一些小的地方去实际使用了之后,就发现,其实一切可能都没有那么难,那些扑朔迷离的流程其实从一开始就很简单,只不过当我们缺乏指点和经验的时候什么都是困难的,当我们有了一点实际经验之后更多的收获是面对这个技术的底气吧