您好,登錄后才能下訂單哦!
道無精粗,人之所見有精粗。如這一間房,人初進(jìn)來,只見一個(gè)大規(guī)模如此。處久,便柱壁之類,一一看得明白。再久,如柱上有些文藻,細(xì)細(xì)都看出來。然只是一間房。
// 搶取訂單函數(shù) public synchronized void grabOrder(Long orderId, Long userId) { // 獲取訂單信息 OrderDO order = orderDAO.get(orderId); if (Objects.isNull(order)) { throw new BizRuntimeException(String.format("訂單(%s)不存在", orderId)); } // 檢查訂單狀態(tài) if (!Objects.equals(order.getStatus, OrderStatus.WAITING_TO_GRAB.getValue())) { throw new BizRuntimeException(String.format("訂單(%s)已被搶", orderId)); } // 設(shè)置訂單被搶 orderDAO.setGrabed(orderId, userId); }
// 搶取訂單函數(shù) public void grabOrder(Long orderId, Long userId) { Long lockId = orderDistributedLock.lock(orderId); try { grabOrderWithoutLock(orderId, userId); } finally { orderDistributedLock.unlock(orderId, lockId); } } // 不帶鎖的搶取訂單函數(shù) private void grabOrderWithoutLock(Long orderId, Long userId) { // 獲取訂單信息 OrderDO order = orderDAO.get(orderId); if (Objects.isNull(order)) { throw new BizRuntimeException(String.format("訂單(%s)不存在", orderId)); } // 檢查訂單狀態(tài) if (!Objects.equals(order.getStatus, OrderStatus.WAITING_TO_GRAB.getValue())) { throw new BizRuntimeException(String.format("訂單(%s)已被搶", orderId)); } // 設(shè)置訂單被搶 orderDAO.setGrabed(orderId, userId); }
// 登錄函數(shù)(示意寫法) public UserVO login(String phoneNumber, String verifyCode) { // 檢查驗(yàn)證碼 if (!checkVerifyCode(phoneNumber, verifyCode)) { throw new ExampleException("驗(yàn)證碼錯(cuò)誤"); } // 檢查用戶存在 UserDO user = userDAO.getByPhoneNumber(phoneNumber); if (Objects.nonNull(user)) { return transUser(user); } // 創(chuàng)建新用戶 return createNewUser(user); } // 創(chuàng)建新用戶函數(shù) private UserVO createNewUser(String phoneNumber) { // 創(chuàng)建新用戶 UserDO user = new UserDO(); ... userDAO.insert(user); // 綁定優(yōu)惠券 couponService.bindCoupon(user.getId(), CouponType.NEW_USER); // 返回新用戶 return transUser(user); }
// 創(chuàng)建新用戶函數(shù) private UserVO createNewUser(String phoneNumber) { // 創(chuàng)建新用戶 UserDO user = new UserDO(); ... userDAO.insert(user); // 綁定優(yōu)惠券 executorService.execute(()->couponService.bindCoupon(user.getId(), CouponType.NEW_USER)); // 返回新用戶 return transUser(user); }
// 創(chuàng)建新用戶函數(shù) private UserVO createNewUser(String phoneNumber) { // 創(chuàng)建新用戶 UserDO user = new UserDO(); ... userDAO.insert(user); // 發(fā)送優(yōu)惠券消息 Long userId = user.getId(); CouponMessageDataVO data = new CouponMessageDataVO(); data.setUserId(userId); data.setCouponType(CouponType.NEW_USER); Message message = new Message(TOPIC, TAG, userId, JSON.toJSONBytes(data)); SendResult result = metaqTemplate.sendMessage(message); if (!Objects.equals(result, SendStatus.SEND_OK)) { log.error("發(fā)送用戶({})綁定優(yōu)惠券消息失敗:{}", userId, JSON.toJSONString(result)); } // 返回新用戶 return transUser(user); }
// 優(yōu)惠券服務(wù)類 @Slf4j @Service public class CouponService extends DefaultMessageListener<String> { // 消息處理函數(shù) @Override @Transactional(rollbackFor = Exception.class) public void onReceiveMessages(MetaqMessage<String> message) { // 獲取消息體 String body = message.getBody(); if (StringUtils.isBlank(body)) { log.warn("獲取消息({})體為空", message.getId()); return; } // 解析消息數(shù)據(jù) CouponMessageDataVO data = JSON.parseObject(body, CouponMessageDataVO.class); if (Objects.isNull(data)) { log.warn("解析消息({})體為空", message.getId()); return; } // 綁定優(yōu)惠券 bindCoupon(data.getUserId(), data.getCouponType()); } }
/** 完成采購動(dòng)作函數(shù)(此處省去獲取采購單/驗(yàn)證狀態(tài)/鎖定采購單等邏輯) */ public void finishPurchase(PurchaseOrder order) { // 完成相關(guān)處理 ...... // 回流采購單(調(diào)用HTTP接口) backflowPurchaseOrder(order); // 設(shè)置完成狀態(tài) purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.FINISHED.getValue()); }
/** 完成采購動(dòng)作函數(shù)(此處省去獲取采購單/驗(yàn)證狀態(tài)/鎖定采購單等邏輯) */ public void finishPurchase(PurchaseOrder order) { // 完成相關(guān)處理 ...... // 設(shè)置完成狀態(tài) purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.FINISHED.getValue()); } /** 執(zhí)行回流動(dòng)作函數(shù)(此處省去獲取采購單/驗(yàn)證狀態(tài)/鎖定采購單等邏輯) */ public void executeBackflow(PurchaseOrder order) { // 回流采購單(調(diào)用HTTP接口) backflowPurchaseOrder(order); // 設(shè)置回流狀態(tài) purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.BACKFLOWED.getValue()); }
/** 執(zhí)行回流動(dòng)作函數(shù)(此處省去獲取采購單/驗(yàn)證狀態(tài)/鎖定采購單等邏輯) */ public void executeBackflow(PurchaseOrder order) { // 完成原始采購單 rawPurchaseOrderDAO.setStatus(order.getRawId(), RawPurchaseOrderStatus.FINISHED.getValue()); // 設(shè)置回流狀態(tài) purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.BACKFLOWED.getValue()); }
/** 采購單服務(wù)接口 */ public interface PurchaseOrderService { /** 完成采購單函數(shù) */ public void finishPurchaseOrder(Long orderId); } /** 采購單服務(wù)實(shí)現(xiàn) */ @Service("purchaseOrderService") public class PurchaseOrderServiceImpl implements PurchaseOrderService { /** 完成采購單函數(shù) */ @Override @Transactional(rollbackFor = Exception.class) public void finishPurchaseOrder(Long orderId) { // 相關(guān)處理 ... // 完成采購單 purchaseOrderService.finishPurchaseOrder(order.getRawId()); } }
/** 執(zhí)行回流動(dòng)作函數(shù)(此處省去獲取采購單/驗(yàn)證狀態(tài)/鎖定采購單等邏輯) */ public void executeBackflow(PurchaseOrder order) { // 完成采購單 purchaseOrderService.finishPurchaseOrder(order.getRawId()); // 設(shè)置回流狀態(tài) purchaseOrderDAO.setStatus(order.getId(), PurchaseOrderStatus.BACKFLOWED.getValue()); }
/** 訂單DAO接口 */ public interface OrderDAO { /** 查詢過期訂單函數(shù) */ @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day)") public List<OrderDO> queryTimeout(); } /** 訂單服務(wù)接口 */ public interface OrderService { /** 查詢過期訂單函數(shù) */ public List<OrderVO> queryTimeout(); }
/** 訂單DAO接口 */ public interface OrderDAO { /** 查詢過期訂單函數(shù) */ @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit 0, #{maxCount}") public List<OrderDO> queryTimeout(@Param("maxCount") Integer maxCount); } /** 訂單服務(wù)接口 */ public interface OrderService { /** 查詢過期訂單函數(shù) */ public List<OrderVO> queryTimeout(Integer maxCount); }
/** 訂單DAO接口 */ public interface OrderDAO { /** 統(tǒng)計(jì)過期訂單函數(shù) */ @Select("select count(*) from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day)") public Long countTimeout(); /** 查詢過期訂單函數(shù) */ @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit #{startIndex}, #{pageSize}") public List<OrderDO> queryTimeout(@Param("startIndex") Long startIndex, @Param("pageSize") Integer pageSize); } /** 訂單服務(wù)接口 */ public interface OrderService { /** 查詢過期訂單函數(shù) */ public PageData<OrderVO> queryTimeout(Long startIndex, Integer pageSize); }
/** 訂單DAO接口 */ public interface OrderDAO { /** 查詢過期訂單函數(shù) */ @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit #{startIndex}, #{pageSize}") public List<OrderDO> queryTimeout(@Param("startIndex") Long startIndex, @Param("pageSize") Integer pageSize); /** 設(shè)置訂單超時(shí)關(guān)閉 */ @Update("update t_order set status = 10 where id = #{orderId} and status = 5") public Long setTimeoutClosed(@Param("orderId") Long orderId) } /** 關(guān)閉過期訂單作業(yè)類 */ public class CloseTimeoutOrderJob extends Job { /** 分頁數(shù)量 */ private static final int PAGE_COUNT = 100; /** 分頁大小 */ private static final int PAGE_SIZE = 1000; /** 作業(yè)執(zhí)行函數(shù) */ @Override public void execute() { for (int i = 0; i < PAGE_COUNT; i++) { // 查詢處理訂單 List<OrderDO> orderList = orderDAO.queryTimeout(i * PAGE_COUNT, PAGE_SIZE); for (OrderDO order : orderList) { // 進(jìn)行超時(shí)關(guān)閉 ...... orderDAO.setTimeoutClosed(order.getId()); } // 檢查處理完畢 if(orderList.size() < PAGE_SIZE) { break; } } } }
當(dāng)滿足查詢條件的數(shù)據(jù),在操作中不再滿足查詢條件時(shí),會(huì)導(dǎo)致后續(xù)分頁查詢中前startIndex(開始序號)條滿足條件的數(shù)據(jù)被跳過。
/** 訂單DAO接口 */ public interface OrderDAO { /** 查詢過期訂單函數(shù) */ @Select("select * from t_order where status = 5 and gmt_create < date_sub(current_timestamp, interval 30 day) limit 0, #{maxCount}") public List<OrderDO> queryTimeout(@Param("maxCount") Integer maxCount); /** 設(shè)置訂單超時(shí)關(guān)閉 */ @Update("update t_order set status = 10 where id = #{orderId} and status = 5") public Long setTimeoutClosed(@Param("orderId") Long orderId) } /** 關(guān)閉過期訂單作業(yè)(定時(shí)作業(yè)) */ public class CloseTimeoutOrderJob extends Job { /** 分頁數(shù)量 */ private static final int PAGE_COUNT = 100; /** 分頁大小 */ private static final int PAGE_SIZE = 1000; /** 作業(yè)執(zhí)行函數(shù) */ @Override public void execute() { for (int i = 0; i < PAGE_COUNT; i++) { // 查詢處理訂單 List<OrderDO> orderList = orderDAO.queryTimeout(PAGE_SIZE); for (OrderDO order : orderList) { // 進(jìn)行超時(shí)關(guān)閉 ...... orderDAO.setTimeoutClosed(order.getId()); } // 檢查處理完畢 if(orderList.size() < PAGE_SIZE) { break; } } } }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。