1. 程式人生 > >ssm系列實戰(5)——實現購物車功能,事務實現提交訂單

ssm系列實戰(5)——實現購物車功能,事務實現提交訂單

本篇為實戰系列第五篇,用session實現購物車功能,事務實現提交訂單

什麼是Session:
使用Cookie和附加URL引數都可以將上一次請求的狀態資訊傳遞到下一次請求中,但是如果傳遞的狀態資訊較多,將極大降低網路傳輸效率和增大伺服器端程式處理的難度。
Session技術是一種將會話狀態儲存在伺服器端的技術 ,它可以比喻成是醫院發放給病人的病歷卡和醫院為每個病人保留的病歷檔案的結合方式 。
客戶端需要接收、記憶和回送 Session的會話標識號,Session可以且通常是藉助Cookie來傳遞會話標識號。
如果以前沒有接觸過的話可以看下面這篇部落格:

這裡我用了一些網上流傳比較廣的工具類,如果有興趣可以看一下,就是原始碼中的utils包下的那些類,熟練使用這些類可以方便你更快地完成更完善的功能。
當我們想讓一本書籍加入購物車時將會呼叫Controller層中的這個方法,傳入的引數是書籍的id。

    @RequestMapping("/add/{itemId}")
    public String addCartItem(@PathVariable Long itemId, HttpServletRequest request, HttpServletResponse response) {
        cartService.addCartItem(itemId, request, response);
        return "cart/success";
    }

接著到了Service層,我們得先在Service層寫一個獲取購物車中商品列表的類,這樣商品才有地方可以放置:

    private List<CartItem> getCartItemList(HttpServletRequest request) {
        //從cookie中取商品列表
        String cartJson = CookieUtil.getCookieValue(request, "ZouCart", true);
        if (cartJson == null) {
            return new ArrayList<>();
        }
        //把json轉換成商品列表
        try
{ List<CartItem> list = JsonUtils.jsonToList(cartJson, CartItem.class); if(list==null){ list = new ArrayList<>(); } return list; } catch (Exception e) { e.printStackTrace(); } return new ArrayList<>(); } } public List<CartItem> getCartItemList(HttpServletRequest request, HttpServletResponse response) { //從cookies中取得商品列表 String cartJson = CookieUtil.getCookieValue(request, "ZouCart", true); if (cartJson == null) { return new ArrayList<>(); } //把json轉換成商品列表 try { List<CartItem> list = JsonUtils.jsonToList(cartJson, CartItem.class); return list; } catch (Exception e) { e.printStackTrace(); } return new ArrayList<>(); }

當我們試圖加入一個商品進入購物車時會呼叫這個方法

    @Override
    public Msg addCartItem(long itemId, HttpServletRequest request, HttpServletResponse response) {
        //取商品資訊
        CartItem cartItem = null;
        //收取購物車商品列表
        List<CartItem> itemList = getCartItemList(request);
        //判斷購物車商品列表是否存在此商品
        for (CartItem item : itemList) {
            //如果存在此商品
            if (item.getId() == itemId) {
                //增加商品數量
                item.setQuantity(item.getQuantity() + 1);
                cartItem = item;
                break;
            }
        }
        if (cartItem == null) {
            cartItem = new CartItem();
            Msg msg = bookService.getBookByPrimary(itemId);
            if (msg.getCode() == 100) {
                Book book = (Book) msg.getExtend().get("book");
                cartItem.setQuantity(1);
                cartItem.setB_id(book.getbId());
                cartItem.setId(book.getbId());
                cartItem.setAuthor(book.getAuthor());
                cartItem.setBook_image(book.getBookImage());
                cartItem.setBook_name(book.getBookName());
                cartItem.setPrice(book.getPrice());
                cartItem.setPubilshing(book.getPubilshing());
            }
            //新增到購物車列表
            itemList.add(cartItem);
        }
        CookieUtil.setCookie(request, response, "ZouCart", JsonUtils.objectToJson(itemList), true);
        return Msg.success();
    }

因為這裡我們是用Session實現購物車功能,不涉及資料庫的使用,所以我們不需要dao層
如果我們要刪除一個商品又怎樣呢:

    public Msg deleteCartItem(long itemId, HttpServletRequest request, HttpServletResponse response) {
        //從cookies中獲取購物車列表
        List<CartItem> itemList = getCartItemList(request);
        //從列表中找到此商品
        for (CartItem cartItem : itemList) {
            if (cartItem.getId() == itemId) {
                itemList.remove(cartItem);
                break;
            }
        }
        //把購物車列表重新寫入cookies
        CookieUtil.setCookie(request, response, "ZouCart", JsonUtils.objectToJson(itemList), true);
        return Msg.success();
    }

當我們進入購物車介面時是可以更改我們所擁有書籍的數量的,那麼就需要一個更新書籍的方法

    public Msg updateItem(long itemId, int quantity, HttpServletRequest request, HttpServletResponse response) {
        List<CartItem> itemList = getCartItemList(request);
        for (CartItem cartItem : itemList) {
            if (cartItem.getId() == itemId) {
                cartItem.setQuantity(quantity);
                break;
            }
        }
        CookieUtil.setCookie(request, response, "ZouCart", JsonUtils.objectToJson(itemList), true);
        return Msg.success();
    }

購物車功能大概介紹完了,接下來就是提交訂單功能了,我們知道,只要是涉及到金錢的我們都需要小心,一個設計上的失誤就可能會導致大量的損失。

事務(Transaction)是併發控制的單位,是使用者定義的一個操作序列。
這些操作要麼都做,要麼都不做,是一個不可分割的工作單位。
通過事務,SQL Server能將邏輯相關的一組操作繫結在一起,以便伺服器保持資料的完整性。
主要用於一些對操作過程的完整性比較高的程式。
比如銀行系統,使用者在轉賬的過程中程式出現錯誤,但是這個轉賬操作沒有完成。那麼這個操作就被退回。

不瞭解事務的可以看下面兩個連結,都很詳細。

資料庫事務詳解
Spring事務管理(詳解+例項)
Spring的註解式事務十分簡單,只需要在Service層對應的需要使用註解的地方加上@Transactional註解即可,注意readOnly一定要是false,代表這不是一個只讀操作,而只讀操作是不需要使用事務的。

    @Transactional(rollbackFor = {Exception.class},propagation = Propagation.REQUIRED,readOnly = false)
    public String create(Allint allint, Order order, List<Detail> details) throws Exception {
        //呼叫建立訂單服務前補全使用者資訊
        //從cookie中取得購物車的內容,然後獲取使用者資訊
        String orderId = new Date().getTime() + UUID.randomUUID().toString().substring(0, 5);
        order.setoId(orderId);
        orderMapper.insert(order);
        int i = 0;
        for (Detail detail : details) {
            long bId = allint.getInts().get(i);
            long stock = bookMapper.checkBookStock(bId);
            long bookNum = detail.getBookNum();
            if (stock < bookNum) {
                throw new Exception();
            }
            //補全訂單明細資訊並存儲
            detail.setoId(orderId);
            orderMapper.insertDetail(detail);
            //減少書本庫存,增加書本銷量
            HashMap<String, Long> map = new HashMap<>();
            map.put("stock", (long) detail.getBookNum());
            map.put("bId", allint.getInts().get(i));
            bookMapper.reduceBook(map);
            i = i + 1;
        }
        return orderId;
    }