當前位置: 妍妍網 > 碼農

Spring Boot中實作訂單30分鐘自動取消的策略

2024-05-13碼農

作者:一只愛擼貓的程式猿
連結:https://juejin.cn/post/7285167401821798400

# 簡介

在電商和其他涉及到線上支付的套用中,通常需要實作一個功能:如果使用者在生成訂單後的一定時間內未完成支付,系統將自動取消該訂單。

本文將詳細介紹基於Spring Boot框架實作訂單30分鐘內未支付自動取消的幾種方案,並提供例項程式碼。

# 方案一:定時任務


用Spring Boot中的 @Scheduled 註解,我們可以輕松地實作定時任務。該任務將周期性地掃描資料庫,檢查未支付的訂單,如果訂單生成30分鐘未支付,則自動取消。

@Componentpublic classOrderCancelSchedule{@Autowiredprivate 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分鐘後過期,過期後消費該訊息,取消訂單。

@Servicepublic classOrderService{@Autowiredprivate 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{@Autowiredprivate OrderService orderService;@RabbitHandlerpublicvoidprocess(String orderId){// 取消訂單 orderService.cancelOrder(orderId); }}

# 方案三:Redis過期事件

利用Redis的鍵過期事件功能,當訂單生成時在Redis中儲存一個鍵,設定30分鐘過期,鍵過期時透過Redis的過期事件通知功能觸發訂單取消操作。

@Servicepublic classOrderService{@Autowiredprivate 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伺服器開啟了相關配置。

下面是具體的步驟和範例:

  1. 首先需要確保Redis的配置檔(通常是redis.conf)中開啟了鍵空間通知功能。你可以透過在配置檔中添加或修改如下配置實作:

notify-keyspace-events "Ex"

這裏的"Ex"表示只監聽鍵過期事件。

  1. 然後在Spring Boot套用中,可以使用RedisMessageListenerContainer來訂閱Redis的鍵過期事件,並指定回呼方法進行處理。範例如下:

@Configurationpublic classRedisConfig{@Autowiredprivate RedisConnectionFactory redisConnectionFactory;@BeanRedisMessageListenerContainer container(){ RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(redisConnectionFactory);// 訂閱所有db的過期事件 container.addMessageListener(new MessageListener() {@OverridepublicvoidonMessage(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分鐘內未支付則自動取消的需求。根據實際業務需求、系統負載和其他因素,可以選擇最適合自己系統的實作方案。每種方案都有其優缺點,需要根據具體情況權衡。

熱門推薦