<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                > 首先我們在這里嚴重的批評一些,在接口訂單的接口中,直接傳訂單金額,而不是使用下單是已經計算好金額的人,這些接口豈不是使用0.01就能將全部的商品都買下來了? 我們回到訂單設計這一個模塊,首先我們在確認訂單的時候就已經將價格計算完成了,那么我們肯定是想將計算結果給保留下來的,至于計算的過程,我們并不希望這個過程還要進行一遍的計算。 我們返回確認訂單的接口,看到這樣一行代碼: ```java @ApiOperation(value = "結算,生成訂單信息", notes = "傳入下單所需要的參數進行下單") public ResponseEntity<ShopCartOrderMergerDto> confirm(@Valid @RequestBody OrderParam orderParam) { orderService.putConfirmOrderCache(userId,shopCartOrderMergerDto); } ``` 這里每經過一次計算,就將整個訂單通過`userId`進行了保存,而這個緩存的時間為30分鐘,當用戶使用 ```java @PostMapping("/submit") @ApiOperation(value = "提交訂單,返回支付流水號", notes = "根據傳入的參數判斷是否為購物車提交訂單,同時對購物車進行刪除,用戶開始進行支付") public ResponseEntity<OrderNumbersDto> submitOrders(@Valid @RequestBody SubmitOrderParam submitOrderParam) { ShopCartOrderMergerDto mergerOrder = orderService.getConfirmOrderCache(userId); if (mergerOrder == null) { throw new YamiShopBindException("訂單已過期,請重新下單"); } // 省略中間一大段。。。 orderService.removeConfirmOrderCache(userId); } ``` 當無法獲取緩存的時候告知用戶訂單過期,當訂單進行提交完畢的時候,將之前的緩存給清除。 我們又回到提交訂單中間這幾行代碼: ```java List<Order> orders = orderService.submit(userId,mergerOrder); ``` 這行代碼也就是提交訂單的核心代碼 ```java eventPublisher.publishEvent(new SubmitOrderEvent(mergerOrder, orderList)); ``` 其中這里依舊是使用時間的方式,將訂單進行提交,看下這個`SubmitOrderEvent`的默認監聽事件。 ```java @Component("defaultSubmitOrderListener") @AllArgsConstructor public class SubmitOrderListener { public void defaultSubmitOrderListener(SubmitOrderEvent event) { // ... } } ``` 這里有幾段值得注意的地方: - 這里是`UserAddrOrder` 并不是`UserAddr`: ```java // 把訂單地址保存到數據庫 UserAddrOrder userAddrOrder = mapperFacade.map(mergerOrder.getUserAddr(), UserAddrOrder.class); if (userAddrOrder == null) { throw new YamiShopBindException("請填寫收貨地址"); } userAddrOrder.setUserId(userId); userAddrOrder.setCreateTime(now); userAddrOrderService.save(userAddrOrder); ``` 這里是將訂單的收貨地址進行了保存入庫的操作,這里是絕對不能只保存用戶的地址id在訂單中的,要將地址入庫,原因是如果用戶在訂單中設置了一個地址,如果用戶在訂單還沒配送的時候,將自己的地址改了的話。如果僅采用關聯的地址,就會出現問題。 - 為每個店鋪生成一個訂單 ```java // 每個店鋪生成一個訂單 for (ShopCartOrderDto shopCartOrderDto : shopCartOrders) { } ``` 這里為每個店鋪創建一個訂單,是為了,以后平臺結算給商家時,每個商家的訂單單獨結算。用戶確認收貨時,也可以為每家店鋪單獨確認收貨。 - 使用雪花算法生成訂單id, 如果對雪花算法感興趣的,可以去搜索下相關內容: ```java String orderNumber = String.valueOf(snowflake.nextId()); ``` 我們不想單多臺服務器生成的id沖突,也不想生成uuid這樣的很奇怪的字符串id,更不想直接使用數據庫主鍵這種東西時,雪花算法就出現咯。 - 當用戶提交訂單的時候,購物車里面勾選的商品,理所當然的要清空掉 ```java // 刪除購物車的商品信息 if (!basketIds.isEmpty()) { basketMapper.deleteShopCartItemsByBasketIds(userId, basketIds); } ``` - 使用數據庫的樂觀鎖,防止超賣: ```java if (skuMapper.updateStocks(sku) == 0) { skuService.removeSkuCacheBySkuId(key, sku.getProdId()); throw new YamiShopBindException("商品:[" + sku.getProdName() + "]庫存不足"); } ``` ```sql update tz_sku set stocks = stocks - #{sku.stocks}, version = version + 1,update_time = NOW() where sku_id = #{sku.skuId} and #{sku.stocks} &lt;= stocks ``` 超賣一直是一件非常令人頭疼的事情,如果對訂單直接加悲觀鎖的話,那么下單的性能將會很差。商城最重要的就是下單啦,要是性能很差,那人家還下個鬼的單喲,所以我們采用數據庫的樂觀鎖進行下單。 所謂樂觀鎖,就是在 where 條件下加上極限的條件,比如在這里就是更新的庫存小于或等于商品的庫存,在這種情況下可以對庫存更新成功,則更新完成了,否則拋異常(真正的定義肯定不是這樣的啦,你可以百度下 “樂觀鎖更新庫存”)。注意這里在拋異常以前,應該將緩存也更新了,不然無法及時更新。 最后我們回到`controller` ```java return ResponseEntity.ok(new OrderNumbersDto(orderNumbers.toString())); ``` 這里面返回了多個訂單項,這里就變成了并單支付咯,在多個店鋪一起進行支付的時候需要進行并單支付的操作,一個店鋪的時候,又要變成一個訂單支付的操作,可是我們只希望有一個統一支付的接口進行調用,所以我們的支付接口要進行一點點的設計咯。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看