作者:一只愛擼貓的程式猿
連結:https://juejin.cn/post/7285167401821798400
# 簡介
在電商和其他涉及到線上支付的套用中,通常需要實作一個功能:如果使用者在生成訂單後的一定時間內未完成支付,系統將自動取消該訂單。
本文將詳細介紹基於Spring Boot框架實作訂單30分鐘內未支付自動取消的幾種方案,並提供例項程式碼。
# 方案一:定時任務
利 用Spring Boot中的 @Scheduled 註解,我們可以輕松地實作定時任務。該任務將周期性地掃描資料庫,檢查未支付的訂單,如果訂單生成30分鐘未支付,則自動取消。
@Component
public classOrderCancelSchedule{
@Autowired
private OrderService orderService;
@Scheduled(cron = "0 0/1 * * * ?")
publicvoidcancelUnpaidOrders(){
List<Order> unpaidOrders = orderService.getUnpaidOrders();
unpaidOrders.forEach(order -> {
if (order.getCreationTime().plusMinutes(30).isBefore(LocalDateTime.now())) {
orderService.cancelOrder(order.getId());
}
});
}
}
# 方案二:延遲佇列
使用訊息佇列(如RabbitMQ)的延遲佇列功能,當訂單生成時將訂單ID推播到延遲佇列,設定30分鐘後過期,過期後消費該訊息,取消訂單。
@Service
public classOrderService{
@Autowired
private RabbitTemplate rabbitTemplate;
publicvoidcreateOrder(Order order){
// 保存訂單至資料庫
saveOrderToDB(order);
// 將訂單ID推播至延遲佇列
rabbitTemplate.convertAndSend("orderDelayExchange", "orderDelayKey", order.getId(), message -> {
message.getMessageProperties().setDelay(30 * 60 * 1000); // 設定延遲時間
return message;
});
}
}
@Component
@RabbitListener(queues = "orderDelayQueue")
public classOrderDelayConsumer{
@Autowired
private OrderService orderService;
@RabbitHandler
publicvoidprocess(String orderId){
// 取消訂單
orderService.cancelOrder(orderId);
}
}
# 方案三:Redis過期事件
利用Redis的鍵過期事件功能,當訂單生成時在Redis中儲存一個鍵,設定30分鐘過期,鍵過期時透過Redis的過期事件通知功能觸發訂單取消操作。
@Service
public classOrderService{
@Autowired
private StringRedisTemplate redisTemplate;
publicvoidcreateOrder(Order order){
// 保存訂單至資料庫
saveOrderToDB(order);
// 在Redis中儲存一個鍵,設定30分鐘過期
redisTemplate.opsForValue().set("order:" + order.getId(), order.getId(), 30, TimeUnit.MINUTES);
}
// 當鍵過期時,Redis會自動呼叫該方法(需要配置Redis的過期事件通知功能)
publicvoidonOrderKeyExpired(String orderId){
cancelOrder(orderId);
}
}
補充一下配置Redis的過期事件通知功能如下:Redis的鍵過期通知是一種典型的釋出-訂閱模式。在Redis中,我們可以訂閱到某些特定的事件。鍵過期事件就是其中之一。
但需要註意,要使用這個功能,需要確保你的Redis伺服器開啟了相關配置。
下面是具體的步驟和範例:
首先需要確保Redis的配置檔(通常是redis.conf)中開啟了鍵空間通知功能。你可以透過在配置檔中添加或修改如下配置實作:
notify-keyspace-events "Ex"
這裏的"Ex"表示只監聽鍵過期事件。
然後在Spring Boot套用中,可以使用RedisMessageListenerContainer來訂閱Redis的鍵過期事件,並指定回呼方法進行處理。範例如下:
@Configuration
public classRedisConfig{
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
RedisMessageListenerContainer container(){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
// 訂閱所有db的過期事件
container.addMessageListener(new MessageListener() {
@Override
publicvoidonMessage(Message message, byte[] pattern){
String expiredKey = message.toString();
if (expiredKey.startsWith("order:")) {
// 處理訂單超時邏輯
String orderId = expiredKey.split(":")[1];
// 這裏呼叫你的服務類方法,處理訂單超時邏輯
// orderService.cancelOrder(orderId);
}
}
}, new PatternTopic("__keyevent@*__:expired"));
return container;
}
}
在這個範例中,"__keyevent@*__:expired"是一個模式匹配的主題,它可以匹配所有資料庫的鍵過期事件。當一個鍵過期時,onMessage方法會被呼叫,你可以在這裏加入你的邏輯來處理訂單的超時取消。
請註意,這裏的程式碼只是一個基本範例。在實際使用中,你可能需要根據自己的需要對程式碼進行相應的調整和最佳化。
# 總結
以上三種方案都可以實作訂單在30分鐘內未支付則自動取消的需求。根據實際業務需求、系統負載和其他因素,可以選擇最適合自己系統的實作方案。每種方案都有其優缺點,需要根據具體情況權衡。
熱門推薦