Java實現(xiàn)訂單超時自動取消的完整設(shè)計方案
在電商、外賣、票務(wù)等業(yè)務(wù)中,“訂單超時自動取消” 是保障資源高效利用的核心功能 —— 比如用戶下單后 30 分鐘未支付,若不自動取消,會導(dǎo)致商品庫存被長期占用,其他用戶無法購買;外賣訂單 15 分鐘未接單,若不取消,會讓用戶長時間等待。但當(dāng)訂單量達(dá)百萬級、超時場景多樣時,簡單的 “定時遍歷數(shù)據(jù)庫” 會徹底失效,需設(shè)計一套適配高并發(fā)、保證數(shù)據(jù)一致性的方案。
本文從 “業(yè)務(wù)場景→核心需求→技術(shù)方案→工程落地” 四層,完整講解訂單超時自動取消的設(shè)計思路,覆蓋不同業(yè)務(wù)規(guī)模的選型與避坑點。
一、先明確:哪些訂單需要 “超時自動取消”
不同業(yè)務(wù)場景的超時規(guī)則差異極大,設(shè)計前需先分類梳理,避免 “一刀切” 的方案無法適配實際需求:
| 訂單類型 | 超時場景 | 超時時間 | 核心痛點(不取消的后果) |
|---|---|---|---|
| 電商普通訂單 | 下單后未支付 | 30 分鐘 | 庫存占用,商品無法賣給其他用戶 |
| 電商預(yù)售訂單 | 付定金后未付尾款 | 24 小時 | 預(yù)售庫存鎖定,影響后續(xù)補(bǔ)貨計劃 |
| 外賣訂單 | 商家未接單 / 騎手未取餐 | 15 分鐘 / 30 分鐘 | 用戶長時間等待,投訴率升高 |
| 酒店 / 票務(wù)訂單 | 預(yù)訂后未支付 | 1 小時 | 房間 / 座位鎖定,錯失潛在客戶 |
| 售后訂單 | 退款申請后未上傳憑證 | 72 小時 | 售后流程卡頓,用戶體驗差 |
核心共性:所有超時場景都需解決 “狀態(tài)閉環(huán)”(超時后訂單從 “待支付 / 待接單” 轉(zhuǎn)為 “已取消”)和 “資源回補(bǔ)”(如庫存、優(yōu)惠券、座位釋放)兩大問題。
二、核心需求拆解:不止 “自動取消”,還要 “可靠”
設(shè)計方案時,需滿足以下功能性與非功能性需求,否則會出現(xiàn) “取消失敗導(dǎo)致資損”“延遲太久引發(fā)投訴” 等問題:
1. 功能性需求
超時時間可配置:支持不同訂單類型設(shè)置不同超時時間(如普通訂單 30 分鐘,預(yù)售訂單 24 小時),且支持動態(tài)修改(如大促期間臨時將未支付超時改為 15 分鐘);
狀態(tài)校驗嚴(yán)格:取消前必須確認(rèn)訂單仍處于 “待超時狀態(tài)”(如用戶在超時前 1 秒支付了,不能再取消);
資源回補(bǔ)完整:取消后需同步回補(bǔ)關(guān)聯(lián)資源(如釋放庫存、返還優(yōu)惠券、解鎖座位),且回補(bǔ)必須成功(不能出現(xiàn) “訂單取消了但庫存沒回來” 的情況);
通知觸達(dá):取消后需告知用戶(如短信、APP 推送),說明取消原因(“訂單超時未支付已自動取消”)。
2. 非功能性需求
數(shù)據(jù)一致性:100% 確保 “該取消的訂單必須取消,不該取消的絕不取消”,不允許出現(xiàn) “重復(fù)取消”(導(dǎo)致庫存多回補(bǔ))或 “漏取消”(導(dǎo)致庫存長期占用);
實時性:超時后需在合理時間內(nèi)取消(如超時后 1 分鐘內(nèi)),不能延遲太久(用戶發(fā)現(xiàn)訂單還在 “待支付”,但實際已超時,會困惑);
高并發(fā)支撐:大促期間訂單量達(dá)百萬級,方案需支撐每秒數(shù)百次的取消請求,且不影響核心下單流程;
可監(jiān)控可追溯:需記錄每筆訂單的 “超時時間、取消時間、取消結(jié)果、回補(bǔ)狀態(tài)”,方便問題排查(如用戶反饋 “訂單沒取消但扣了優(yōu)惠券”,能快速定位原因)。
三、技術(shù)方案對比:3 種主流方案的優(yōu)劣與選型
目前行業(yè)內(nèi)實現(xiàn)訂單超時自動取消的方案主要有 3 種,需根據(jù)業(yè)務(wù)規(guī)模、實時性要求選擇適配方案:
| 方案類型 | 核心原理 | 實時性 | 一致性 | 并發(fā)支撐 | 適用場景 |
|---|---|---|---|---|---|
| 分布式定時任務(wù) | 定時遍歷數(shù)據(jù)庫 / 緩存,篩選超時訂單 | 中(分鐘級) | 高(需加鎖) | 中(百萬級訂單) | 電商大促、庫存占用敏感場景 |
| 延遲隊列 | 訂單創(chuàng)建時發(fā)送延遲消息,超時后消費(fèi) | 高(秒級) | 高(消息可靠) | 高(千萬級訂單) | 外賣、票務(wù)等實時性要求高的場景 |
| Redis 過期回調(diào) | 訂單 ID 作為 Redis Key,過期后觸發(fā)回調(diào) | 低(秒 - 分鐘級,依賴 Redis 過期策略) | 中(可能漏回調(diào)) | 低(十萬級訂單) | 中小業(yè)務(wù)、實時性要求不高的場景 |
方案 1:分布式定時任務(wù)(適合海量訂單,一致性優(yōu)先)
1. 原理
訂單創(chuàng)建時,記錄 “訂單創(chuàng)建時間” 和 “超時時間”(如create_time=1688888888,timeout=1800秒);
用分布式定時任務(wù)框架(如 XXL-Job、Elastic-Job)按固定頻率(如每分鐘)執(zhí)行任務(wù),篩選出 “當(dāng)前時間 - create_time ≥ timeout” 且狀態(tài)為 “待支付” 的訂單;
對篩選出的訂單執(zhí)行取消邏輯(狀態(tài)修改 + 資源回補(bǔ))。
2. 關(guān)鍵實現(xiàn)細(xì)節(jié)
篩選優(yōu)化:避免全表掃描,在create_time和order_status上建立聯(lián)合索引(如idx_create_status (order_status, create_time)),查詢 SQL 示例:
SELECT order_id FROM orders WHERE order_status = 'PENDING_PAY' -- 待支付狀態(tài) AND create_time + timeout <= UNIX_TIMESTAMP(NOW()) -- 已超時 LIMIT 1000; -- 分批處理,避免一次處理太多訂單
并發(fā)控制:用分布式鎖(如 Redis 鎖)防止同一訂單被多個定時任務(wù)實例重復(fù)處理,鎖 Key 為order:cancel:lock:{order_id},持有時間設(shè)為 30 秒(足夠完成一次取消流程);
失敗重試:處理失敗的訂單(如資源回補(bǔ)失敗),加入重試隊列(如 Redis List),單獨用一個定時任務(wù)重試(重試次數(shù) 3 次,每次間隔 5 分鐘),仍失敗則觸發(fā)人工告警。
3. 優(yōu)劣勢
- 優(yōu)勢:不依賴復(fù)雜中間件,實現(xiàn)簡單;支持海量訂單篩選,適合大促場景;
- 劣勢:實時性中等(依賴定時頻率,最快每分鐘執(zhí)行一次,超時后可能延遲 1 分鐘才取消);定時任務(wù)執(zhí)行時會對數(shù)據(jù)庫造成一定壓力(需控制分批大小)。
4. 選型建議
適合 “訂單量百萬級 +,實時性要求不極致(允許 1 分鐘延遲)” 的場景,如電商普通訂單、預(yù)售訂單。
方案 2:延遲隊列(適合實時性高,中高并發(fā))
1. 原理
訂單創(chuàng)建時,不直接寫入數(shù)據(jù)庫監(jiān)控,而是向延遲隊列發(fā)送一條 “延遲消息”,消息內(nèi)容包含order_id,延遲時間設(shè)為訂單的超時時間(如 30 分鐘);
延遲隊列在消息達(dá)到延遲時間后,將消息投遞到 “取消消費(fèi)隊列”;
消費(fèi)端監(jiān)聽 “取消消費(fèi)隊列”,收到消息后執(zhí)行訂單取消邏輯。
2. 主流延遲隊列實現(xiàn)對比
| 中間件 | 實現(xiàn)方式 | 優(yōu)點 | 缺點 |
|---|---|---|---|
| RabbitMQ | 基于 “死信隊列 + TTL”(消息過期后進(jìn)入死信隊列) | 輕量,易集成,支持消息持久化 | 不支持動態(tài)修改延遲時間;延遲精度中等(秒級) |
| RocketMQ | 原生支持定時消息(延遲級別或自定義時間) | 延遲精度高(毫秒級),支持海量消息 | 依賴 RocketMQ,部署成本稍高;自定義延遲時間需配置 |
| Kafka | 基于 “時間輪 + 主題分區(qū)”(如 Kafka Streams) | 高吞吐,適合千萬級訂單 | 實現(xiàn)復(fù)雜,需自定義時間輪邏輯;不支持消息重試 |
3. 關(guān)鍵實現(xiàn)細(xì)節(jié)(以 RocketMQ 為例)
消息發(fā)送:訂單創(chuàng)建時發(fā)送定時消息,指定延遲時間為訂單超時時間:
// RocketMQ發(fā)送定時消息示例(Java)
public void sendDelayMsg(String orderId, long timeoutSeconds) {
Message msg = new Message("order_timeout_topic", // 主題
"cancel_tag", // 標(biāo)簽
orderId.getBytes()); // 消息體(訂單ID)
// 設(shè)置定時時間:timeoutSeconds秒后投遞(RocketMQ支持自定義毫秒級延遲)
msg.setDelayTimeMs(timeoutSeconds * 1000);
// 發(fā)送消息(開啟事務(wù),確?!坝唵蝿?chuàng)建成功”和“消息發(fā)送成功”原子性)
rocketMQTemplate.send(msg);
}
事務(wù)保障:用 “本地事務(wù)表 + 消息確認(rèn)” 確保 “訂單創(chuàng)建” 和 “延遲消息發(fā)送” 的原子性(避免 “訂單創(chuàng)建了但消息沒發(fā)出去,導(dǎo)致漏取消”):
- 訂單創(chuàng)建時,先寫入 “訂單表” 和 “本地事務(wù)表”(記錄order_id和msg_status=UNSENT);
- 發(fā)送延遲消息,若發(fā)送成功,更新 “本地事務(wù)表”msg_status=SENT;
- 啟動定時任務(wù),掃描 “本地事務(wù)表” 中msg_status=UNSENT的訂單,重新發(fā)送消息。
消費(fèi)邏輯:消費(fèi)端收到消息后,先查訂單狀態(tài),再執(zhí)行取消:
@RocketMQMessageListener(topic = "order_timeout_topic", consumerGroup = "cancel_consumer_group")
public class OrderCancelConsumer implements RocketMQListener<String> {
@Autowired
private OrderService orderService;
@Override
public void onMessage(String orderId) {
// 1. 查訂單當(dāng)前狀態(tài)(必須加鎖,防止并發(fā)支付)
OrderDO order = orderService.getOrderWithLock(orderId);
if (order == null || !"PENDING_PAY".equals(order.getStatus())) {
return; // 訂單不存在或已支付,不取消
}
// 2. 執(zhí)行取消邏輯(狀態(tài)修改+資源回補(bǔ))
boolean cancelSuccess = orderService.cancelOrder(order);
if (!cancelSuccess) {
// 3. 取消失敗,發(fā)送重試消息(延遲5分鐘后重試)
sendDelayMsg(orderId, 300);
}
}
}
4. 優(yōu)劣勢
- 優(yōu)勢:實時性高(超時后秒級內(nèi)取消);消息持久化,不擔(dān)心漏取消;支持高并發(fā)(RocketMQ 每秒可處理數(shù)萬條消息);
- 劣勢:依賴中間件(如 RocketMQ),需維護(hù)中間件集群;動態(tài)修改超時時間較復(fù)雜(需先刪除舊消息,再發(fā)新消息)。
5. 選型建議
適合 “實時性要求高(如外賣、票務(wù))、訂單量中高(十萬 - 千萬級)” 的場景。
方案 3:Redis 過期回調(diào)(適合中小業(yè)務(wù),快速落地)
1. 原理
- 訂單創(chuàng)建時,將order_id作為 Redis Key,值為訂單狀態(tài)(如PENDING_PAY),并設(shè)置 Key 的過期時間為訂單超時時間(如 30 分鐘);
- 開啟 Redis 的keyspace notifications(鍵空間通知),當(dāng) Key 過期時,Redis 會發(fā)送 “Key 過期事件”;
- 應(yīng)用端監(jiān)聽 Redis 過期事件,收到事件后執(zhí)行訂單取消邏輯。
2. 關(guān)鍵實現(xiàn)細(xì)節(jié)
開啟 Redis 通知:在 Redis 配置文件中開啟過期通知(notify-keyspace-events "Ex"),或通過命令臨時開啟:
config set notify-keyspace-events Ex
監(jiān)聽過期事件:用 Redis 客戶端(如 Redisson)監(jiān)聽事件:
// Redisson監(jiān)聽Redis過期事件示例
public void listenRedisExpireEvent() {
RPatternTopic topic = redissonClient.getPatternTopic("__keyevent@0__:expired");
topic.addListener(String.class, (channel, orderId) -> {
// 判斷是否為訂單超時Key(避免監(jiān)聽無關(guān)Key)
if (orderId.startsWith("order:timeout:")) {
String realOrderId = orderId.replace("order:timeout:", "");
// 執(zhí)行取消邏輯(同延遲隊列消費(fèi)邏輯)
orderService.handleTimeoutCancel(realOrderId);
}
});
}
規(guī)避 Redis 過期延遲:Redis 的過期刪除采用 “惰性刪除 + 定期刪除” 策略,可能導(dǎo)致 Key 過期后幾秒甚至幾分鐘才觸發(fā)回調(diào),需在取消邏輯中再次校驗訂單是否真的超時:
public void handleTimeoutCancel(String orderId) {
OrderDO order = orderService.getOrder(orderId);
if (order == null) return;
// 二次校驗:當(dāng)前時間是否真的超過訂單超時時間(避免Redis回調(diào)延遲導(dǎo)致誤判)
long currentTime = System.currentTimeMillis() / 1000;
long timeoutTime = order.getCreateTime() + order.getTimeoutSeconds();
if (currentTime < timeoutTime || !"PENDING_PAY".equals(order.getStatus())) {
return;
}
// 執(zhí)行取消邏輯
orderService.cancelOrder(order);
}
3. 優(yōu)劣勢
- 優(yōu)勢:實現(xiàn)簡單,無需依賴復(fù)雜中間件;開發(fā)成本低,適合中小團(tuán)隊;
- 劣勢:實時性低(依賴 Redis 過期策略,可能延遲幾分鐘);Redis 集群環(huán)境下,過期事件可能丟失(部分客戶端不支持集群監(jiān)聽);不適合海量訂單(Redis 處理過期事件的能力有限)。
4. 選型建議
適合 “中小業(yè)務(wù)、訂單量十萬級以內(nèi)、實時性要求不高” 的場景(如小型電商、內(nèi)部訂單系統(tǒng))。
四、核心業(yè)務(wù)邏輯:取消流程的 “避坑指南”
無論選擇哪種技術(shù)方案,訂單取消的核心業(yè)務(wù)邏輯都需嚴(yán)格遵循 “校驗→取消→回補(bǔ)→通知” 四步,且每一步都要處理異常,確保數(shù)據(jù)一致:
1. 第一步:訂單狀態(tài)嚴(yán)格校驗(防誤取消)
取消前必須用 “排他鎖” 鎖定訂單,防止用戶在取消過程中支付(如用戶超時前 1 秒支付,同時系統(tǒng)在執(zhí)行取消):
// 用數(shù)據(jù)庫行鎖鎖定訂單(SELECT ... FOR UPDATE)
@Transactional
public OrderDO getOrderWithLock(String orderId) {
return orderMapper.selectByOrderIdForUpdate(orderId);
}
// 校驗邏輯
public boolean checkCanCancel(OrderDO order) {
// 1. 訂單狀態(tài)必須是“待支付/待接單”等可取消狀態(tài)
if (!Arrays.asList("PENDING_PAY", "PENDING_ACCEPT").contains(order.getStatus())) {
log.info("訂單{}狀態(tài)為{},不可取消", order.getOrderId(), order.getStatus());
return false;
}
// 2. 訂單確實已超時(二次校驗,避免定時任務(wù)/Redis回調(diào)延遲)
long currentTime = System.currentTimeMillis() / 1000;
long timeoutTime = order.getCreateTime() + order.getTimeoutSeconds();
if (currentTime < timeoutTime) {
log.info("訂單{}未超時(當(dāng)前時間{},超時時間{}),不可取消",
order.getOrderId(), currentTime, timeoutTime);
return false;
}
return true;
}
2. 第二步:訂單狀態(tài)修改(原子性)
修改訂單狀態(tài)必須在事務(wù)中執(zhí)行,確保 “狀態(tài)修改” 與 “資源回補(bǔ)” 要么同時成功,要么同時失?。?/p>
@Transactional
public boolean cancelOrder(OrderDO order) {
// 1. 再次校驗(防止事務(wù)等待期間狀態(tài)變化)
if (!checkCanCancel(order)) {
return false;
}
// 2. 修改訂單狀態(tài)為“已取消”
int updateCount = orderMapper.updateStatus(order.getOrderId(), "CANCELED", "TIMEOUT");
if (updateCount != 1) {
log.error("訂單{}修改狀態(tài)失敗,影響行數(shù){}", order.getOrderId(), updateCount);
throw new RuntimeException("訂單狀態(tài)修改失敗"); // 觸發(fā)事務(wù)回滾
}
// 3. 回補(bǔ)關(guān)聯(lián)資源(庫存、優(yōu)惠券、座位等)
try {
// 回補(bǔ)庫存
inventoryService.releaseInventory(order.getSkuId(), order.getQuantity());
// 回補(bǔ)優(yōu)惠券(如果下單時鎖定了優(yōu)惠券)
if (order.getCouponId() != null) {
couponService.unlockCoupon(order.getUserId(), order.getCouponId());
}
// 回補(bǔ)座位/房間(票務(wù)/酒店訂單)
if (order.getOrderType().equals("TICKET")) {
ticketService.unlockSeat(order.getSeatId());
}
} catch (Exception e) {
log.error("訂單{}資源回補(bǔ)失敗", order.getOrderId(), e);
throw new RuntimeException("資源回補(bǔ)失敗"); // 觸發(fā)事務(wù)回滾,訂單狀態(tài)恢復(fù)為待支付
}
// 4. 記錄取消日志(用于問題排查)
orderLogService.recordLog(order.getOrderId(), "ORDER_CANCELED", "訂單超時自動取消");
return true;
}
3. 第三步:用戶通知(提升體驗)
取消后需通過多渠道通知用戶,說明原因和后續(xù)操作(如 “訂單已取消,庫存已釋放,可重新下單”):
public void sendCancelNotice(OrderDO order) {
// 1. 短信通知(核心渠道,確保用戶能收到)
smsService.send(order.getPhone(), String.format(
"【XX平臺】您的訂單%s因超時未支付已自動取消,庫存已釋放,可重新下單。",
order.getOrderId()
));
// 2. APP推送(針對已安裝APP的用戶)
pushService.send(order.getUserId(), "訂單取消通知",
String.format("訂單%s已自動取消,原因:超時未支付", order.getOrderId()));
// 3. 站內(nèi)信(補(bǔ)充渠道)
messageService.sendInboxMsg(order.getUserId(), "訂單取消",
String.format("訂單%s于%s因超時未支付自動取消,如有疑問請聯(lián)系客服。",
order.getOrderId(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
}
五、工程落地:監(jiān)控與運(yùn)維不可少
即使方案設(shè)計完善,也需配套監(jiān)控與運(yùn)維措施,避免 “問題發(fā)生后才發(fā)現(xiàn)”:
1. 核心監(jiān)控指標(biāo)
| 指標(biāo)名稱 | 監(jiān)控頻率 | 閾值建議 | 告警方式 |
|---|---|---|---|
| 超時訂單總量 | 1 分鐘 | 無(需觀察趨勢) | 無(用于業(yè)務(wù)分析) |
| 取消成功率 | 1 分鐘 | <99.9% | 短信 + 釘釘告警 |
| 取消延遲時間 | 1 分鐘 | >3 分鐘(超時后到取消的時間) | 短信告警 |
| 資源回補(bǔ)失敗率 | 1 分鐘 | >0.1% | 電話 + 短信告警 |
| 定時任務(wù) / 延遲隊列堆積數(shù) | 10 秒 | >1000 條 | 釘釘 + 郵件告警 |
2. 日志與追溯
每筆訂單的取消流程需記錄完整日志,包含 “訂單 ID、觸發(fā)方式(定時任務(wù) / 延遲隊列)、開始時間、結(jié)束時間、狀態(tài)、回補(bǔ)資源列表、失敗原因(如有)”;
用 ELK(Elasticsearch+Logstash+Kibana)存儲和查詢?nèi)罩?,支持?“訂單 ID、時間范圍、失敗原因” 檢索,方便快速排查問題(如用戶反饋 “訂單沒取消”,輸入訂單 ID 即可查看取消日志)。
3. 應(yīng)急方案
- 取消失敗應(yīng)急:針對 “取消失敗且重試多次仍失敗” 的訂單,觸發(fā)人工介入流程(如發(fā)送工單給運(yùn)營,手動取消并回補(bǔ)資源);
- 中間件故障應(yīng)急:若延遲隊列 / Redis 故障,臨時切換為 “分布式定時任務(wù)” 方案,確保取消功能不中斷;
- 大促峰值應(yīng)急:大促期間提前擴(kuò)容定時任務(wù) / 延遲隊列的節(jié)點,避免因并發(fā)過高導(dǎo)致堆積。
六、方案選型速查表
| 業(yè)務(wù)規(guī)模 | 實時性要求 | 推薦方案 | 關(guān)鍵注意點 |
|---|---|---|---|
| 中小業(yè)務(wù)(<10 萬單 / 天) | 低(允許 5 分鐘延遲) | Redis 過期回調(diào) | 開啟 Redis 通知,二次校驗超時時間 |
| 中業(yè)務(wù)(10 萬 - 100 萬單 / 天) | 中(允許 1 分鐘延遲) | 分布式定時任務(wù)(XXL-Job) | 分批處理,加分布式鎖防重復(fù)取消 |
| 大業(yè)務(wù)(>100 萬單 / 天) | 高(秒級) | 延遲隊列(RocketMQ) | 消息持久化,事務(wù)保障訂單與消息一致性 |
總結(jié)
訂單超時自動取消功能的設(shè)計,核心不是 “選哪種技術(shù)方案”,而是 “確保一致性與可靠性”—— 無論用定時任務(wù)、延遲隊列還是 Redis,都需做到:
- 取消前嚴(yán)格校驗訂單狀態(tài),防誤判;
- 取消中用事務(wù)保障 “狀態(tài)修改 + 資源回補(bǔ)” 原子性,防資損;
- 取消后完善監(jiān)控與日志,防問題不可追溯。
最終,方案需適配自身業(yè)務(wù)規(guī)模與實時性要求:中小業(yè)務(wù)用 Redis 快速落地,中大規(guī)模用定時任務(wù)或延遲隊列保障可靠,核心是 “不追求最復(fù)雜的技術(shù),只選最適合的方案”。
以上就是Java實現(xiàn)訂單超時自動取消的完整設(shè)計方案的詳細(xì)內(nèi)容,更多關(guān)于Java訂單超時自動取消的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java如何讀寫Properties配置文件(Properties類)
這篇文章主要介紹了Java如何讀寫Properties配置文件(Properties類),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05
Springboot使用異步方法優(yōu)化Service邏輯,提高接口響應(yīng)速度方式
這篇文章主要介紹了Springboot使用異步方法優(yōu)化Service邏輯,提高接口響應(yīng)速度方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-06-06
SpringBoot使用SSE進(jìn)行實時通知前端的實現(xiàn)代碼
這篇文章主要介紹了SpringBoot使用SSE進(jìn)行實時通知前端,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06
MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析詳解
這篇文章主要介紹了MyBatis Plus插件機(jī)制與執(zhí)行流程原理分析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09

