购物车的实现

本文详细地址出自于:http://www.endless365.com/article/get?type=tec&id=150


购物车是一个比较复杂的系统,一般会和订单、商品、库存、会员、促销等模块有关系,按照电子商城的功能需求,购物车模块可大可小,所以按照功能需求做的同时考虑后期的扩展,以下对一个比较简单购物车进行初步分析,如果有什么问题或者愿意和我交流的,请联系评论或者email我,我的email是tec_feng@hotmail.com。

    我从几个方面去分析:

    1、什么是购物车。

    2、购物车的入口。

    3、购物车的出口。

    4、购物车的状态和管理。

    5、购物车的存储。

    

    1、购物车

    简单的理解,方便用户将自己心仪的商品放在一个可展示和保存的集合里面,在选购完以后用于集中处理购买。

    2、购物车的入口

    作为电子商务网站,最重要的目的就是诱导顾客购买自己的产品,所以恰当的购物车入口是非常重要的,常见的购物车入口有:商品详情页面、收藏夹页面、推荐商品页面、以购买成功的订单页面、已取消订单商品的页面、排行推荐的页面等。

    3、购物车的出口

    常见的购物车出口有:结算、删除、加入收藏等

    4、购物车的状态和管理

    状态:

                登陆前购物车

                        价格,数量,是否过期,是否存在库存等

                登陆后购物车

                        价格,数量,折扣,优惠券,是否过期,是否存在库存等


    5、购物车的存储。

        在对购物车的代码实现方面这一块非常的重要。

        按照我的里面,我将购物车分为登陆前购物车、登陆后购物车和登陆后两种购物车的合并。

        对于存储当然就存在以下几个比较常见的疑问:

                1、加入购物车后的商品,等到第二次登陆该网站的时候,商品却消失了?

                2、为什么我还一台电脑,购物车的商品却没有了?

                3、我没有往购物车添加商品,为什么我的购物车里面有了商品?

                4、我在网站上将商品添加到了购物车,我下次登陆,或者更换电脑登陆是否同样能够看到我加入购物车的东西,不管我是否加入购物车有没有登陆?

                ......

                根据以上几种疑问衍生出购物车商品的存储。

                cookie存储,会话session存储,本地存储,数据库存储,本地数据库存储。

                针对这些存储介绍一下他们的特点。

                cookie存储:

                        大多数浏览器支持最大为 4096 字节的 Cookie;

                        浏览器还限制站点可以在用户计算机上存储的 Cookie 的数量。大多数浏览器只允许每个站点存储 20 个 Cookie;

                        如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。有些浏览器还会对它们将接受的来自所有站点的 Cookie 总数作出绝对限制,通常为 300 个;

                        Cookie默认情况都会随着Http请求发送到后台服务器,但并不是所有请求都需要Cookie的,比如:js、css、图片等请求则不需要cookie;

                        Cookie可以通过一些设置来管理他的过期时间等,一旦过期,所保存的信息将丢失

                        浏览器有可能禁止cookies。

            会话session存储:

                        所有保存的信息都存放在session当中,一旦会话结束,下次再次登陆网站,保存信息将丢失

            本地存储:

                        会话级别本地存储sessionStorage和永久本地存储localStorage

                        sessionStorage:通过此对象可以直接操作存储在浏览器中的会话级别的WebStorage。存储在sessionStorage中的数据首先是Key-Value形式的,另外就是它跟浏览器当前会话相关,当会话结束后,数据会自动清除,跟未设置过期时间的Cookie类似。

                        localStorage:便于用户存储永久存储的Web端的数据。而且数据不会随着Http请求发送到后台服务器,而且存储数据的大小机会不用考虑,因为在HTML5的标准中要求浏览器至少要支持到4MB.所以,这完全是颠覆了Cookie的限制,为Web应用在本地存储复杂的用户痕迹数据提供非常方便的技术支持。

            数据库存储:

                        将所有的信息都存储在服务器数据库中,该种方式购物车信息被永久存储,但是需要额外的表进行存储并需要和服务器频繁的打交道。

            本地数据库存储:

                        Html5提供了一个浏览器端的数据库支持,允许我们直接通JS的API在浏览器端创建一个本地的数据库,而且支持标准的SQL的CRUD操作,让离线的Web应用更加方便的存储结构化的数据。


        根据这次开发的功能,我选择了localStorage来保存登陆前的购物车。

        首先简单的介绍一下localStroage的使用:

        localStorage存储数据类似于key-value形式,提供了四个方法来辅助我们进行对本地存储做相关操作。
        (1)setItem(key,value):添加本地存储数据。两个参数,非常简单就不说了。
        (2)getItem(key):通过key获取相应的Value。
        (3)removeItem(key):通过key删除本地数据。
        (4)clear():清空数据。

        由于在开发过程中使用了百度ueditor进行商品信息的编辑,发现ueditor也将一些缓存信息和配置等放在了localStroage中,所以对于购物车的商品信息和其他应用存放在localStroage导致一些混淆,以至于localStorage不能只被购物车所使用,所有考虑了两种方法出去处理,一种是将购物车封装成一个独有key和数据value进行处理,这样所有的购物车信息都只存在于这个独有key的value中;另外一种方式就是给每一个购物车的key加上特有的标识,这样通过标识可以唯一的获取到购物车的信息。

        以下是我对localStorage的一些操作。

[js]   view plain  copy
  1.     //获取本地购物车的json字符串  
  2.     function getLocalCartParam(){  
  3.         var param = "[";  
  4.         var storage = window.localStorage;  
  5.         for (var i = 0, len = storage.length; i < len; i++) {  
  6.             var key = storage.key(i);  
  7.             if(key.indexOf("THX") == -1){  
  8.                 continue;  
  9.             }  
  10.             var item = storage.getItem(key);  
  11.             param += ("{\"productId\":" + key + ",\"count\":" + item + "},");  
  12.         }  
  13.         param += "]";  
  14.         return param;  
  15.     }  
  16.     //获取本地购物车的数量  
  17.     function getLocalCartCount(){  
  18.         var storage = window.localStorage;  
  19.         var count = 0;  
  20.         for (var i = 0, len = storage.length; i < len; i++) {  
  21.             var key = storage.key(i);  
  22.             if(key.indexOf("THX") != -1){  
  23.                 count ++;      
  24.             }  
  25.         }      
  26.         return count;  
  27.     }  
  28.     //保存商品到购物车中  
  29.     function setLocalCart(productId){  
  30.         var storage = window.localStorage;  
  31.         var bl = true;  
  32.         var tempProductId = "THX"+productId;  
  33.         for (var i = 0, len = storage.length; i < len; i++) {  
  34.             var key = storage.key(i);  
  35.             if (tempProductId == key) {  
  36.                 var value = storage.getItem(key);  
  37.                 localStorage.setItem(tempProductId, parseInt(value) + 1);  
  38.                 bl = false;  
  39.                 break;  
  40.             }  
  41.         }  
  42.         if (bl) {  
  43.             localStorage.setItem(tempProductId, 1);  
  44.         }  
  45.         var count = getLocalCartCount();  
  46.         setCartNumber(count);  
  47.     }  

        登陆后,所有的购物车信息存储到数据库中

        以下代码是对于购物车管理的serviceImpl的实现简单代码

[java]   view plain  copy
  1. package com.liveman.shop.service.impl;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import java.util.Map;  
  6.   
  7. import javax.annotation.Resource;  
  8.   
  9. import org.springframework.beans.factory.annotation.Autowired;  
  10. import org.springframework.stereotype.Component;  
  11.   
  12. import com.fasterxml.jackson.core.type.TypeReference;  
  13. import com.fasterxml.jackson.databind.ObjectMapper;  
  14. import com.liveman.shop.dao.order.CartMapper;  
  15. import com.liveman.shop.entity.order.Cart;  
  16. import com.liveman.shop.entity.order.CartJson;  
  17. import com.liveman.shop.entity.order.CartVO;  
  18. import com.liveman.shop.entity.product.Product;  
  19. import com.liveman.shop.global.DateTool;  
  20. import com.liveman.shop.service.CartService;  
  21. import com.liveman.shop.service.ProductService;  
  22.   
  23. /** 
  24.  *  
  25.  * @author sunny 
  26.  * 
  27.  */  
  28. @Component("cartService")  
  29. public class CartServiceImpl implements CartService{  
  30.       
  31.     @Resource  
  32.     CartMapper dao;  
  33.     @Autowired  
  34.     ProductService productService;  
  35.       
  36.     @Override  
  37.     public int insertCart(Cart cart) {  
  38.         Cart temp = dao.findCartByProductId(cart);  
  39.         if(temp != null){  
  40.             int productCount = temp.getProductCount();  
  41.             temp.setProductCount(productCount+cart.getProductCount());  
  42.             dao.updateCartById(temp);  
  43.         }else{  
  44.             dao.insertCart(cart);  
  45.         }  
  46.         int count = dao.findCartCount(cart.getUserId());  
  47.         return count;  
  48.           
  49.     }  
  50.   
  51.     @Override  
  52.     public void deleteCartByIds(List<Integer> ids) {  
  53.         if(ids.size()!=0){  
  54.             dao.deleteCartByIds(ids);  
  55.         }  
  56.     }  
  57.   
  58.     @Override  
  59.     public void updateCartById(int id, int count) {  
  60.         Cart temp = dao.findCartById(id);  
  61.         temp.setProductCount(count);  
  62.         dao.updateCartById(temp);  
  63.     }  
  64.   
  65.     @Override  
  66.     public List<CartVO> findCartsByUserId(int userId) {  
  67.         List<CartVO> carts = dao.findCartsByUserId(userId);  
  68.         return carts;  
  69.     }  
  70.   
  71.     @Override  
  72.     public void deleteAllCartsByUserId(int userId) {  
  73.         dao.deleteAllCartsByUserId(userId);  
  74.     }  
  75.   
  76.     @Override  
  77.     public int getCartCount(int userId) {  
  78.         int count = dao.findCartCount(userId);  
  79.         return count;  
  80.     }  
  81.   
  82.     @Override  
  83.     public List<CartVO> findCartsByProductIds(int userId, List<Integer> ids) {  
  84.         List<CartVO> vos = new ArrayList<>();  
  85.         if(ids.size() !=0){  
  86.             vos = dao.findCartsByProductIds(userId, ids);  
  87.         }  
  88.         return vos;  
  89.     }  
  90.   
  91.     @Override  
  92.     public List<CartVO> findCartsByProductIds(String jsons) {  
  93.         if(jsons == null ||"".equals(jsons.trim())){  
  94.             return new ArrayList<CartVO>();  
  95.         }  
  96.         List<CartJson> cartJsons = jsonToList(jsons);  
  97.         List<Integer> productIds = new ArrayList<>();  
  98.          for(CartJson json : cartJsons){  
  99.              productIds.add(json.getProductId());  
  100.          }  
  101.         Map<Integer,Product> maps = productService.getSimpleProductByIds(productIds);  
  102.         List<CartVO> vos = new ArrayList<>();  
  103.         for(CartJson json : cartJsons){  
  104.             CartVO vo = new CartVO();  
  105.             Cart cart = new Cart();  
  106.             cart.setProductId(json.getProductId());  
  107.             cart.setProductCount(json.getCount());  
  108.             vo.setCart(cart);  
  109.             vo.setProduct(maps.get(json.getProductId()));  
  110.             vos.add(vo);  
  111.         }  
  112.         return vos;  
  113.     }  
  114.   
  115.     @Override  
  116.     public void mergeCart(int userId,String jsons) {  
  117.         if(jsons == null ||"".equals(jsons.trim())){  
  118.             return;  
  119.         }  
  120.         List<CartJson> cartJsons = jsonToList(jsons);  
  121.         Cart cart = new Cart();  
  122.          for(CartJson json : cartJsons){  
  123.              cart.setCreateTime(DateTool.getCurrentDateCN());  
  124.              cart.setUserId(userId);  
  125.              cart.setProductCount(json.getCount());  
  126.              cart.setProductId(json.getProductId());  
  127.              insertCart(cart);  
  128.          }  
  129.     }  
  130.       
  131.     private List<CartJson> jsonToList(String jsons){  
  132.         jsons = jsons.replace("THX""");  
  133.         jsons = jsons.substring(0, jsons.lastIndexOf(",")) +"]";  
  134.         ObjectMapper mapper = new ObjectMapper();    
  135.         List<CartJson> cartJsons = new ArrayList<>();  
  136.          try {  
  137.              cartJsons = mapper.readValue(jsons, new TypeReference<List<CartJson>>() {});  
  138.         } catch (Exception e) {  
  139.             e.printStackTrace();  
  140.         }  
  141.          return cartJsons;  
  142.     }  
  143.   
  144. }  

    当用户登录的时候,牵扯到了未登录购物车和登陆购物车的合并,当用户登录后,将未登录购物车里面的信息合并到用户登录后购物车中,成功以后,清除localStorage里面的购物车信息。

    我的实现思路是当数据合并后,通过springmvc的转向跳转到前台清理页面,清理完成以后跳转到需要的页面。

[java]   view plain  copy
  1. 后台跳转代码:  
  2. @RequestMapping(value = "/login", method = RequestMethod.POST)  
  3.     public ModelAndView login(HttpSession session, String email, String password,String hiddenCarts) {  
  4.         ReturnStatus rs = userService.login(email, password);  
  5.         if (rs.getCode() == 1) {  
  6.             User user = (User) rs.getUserData();  
  7.             session.setAttribute("user", user);  
  8.             cartService.mergeCart(user.getId(), hiddenCarts);  
  9.             ModelAndView m = new ModelAndView("order/clearTempCart");  
  10.             m.addObject("count",cartService.getCartCount(user.getId()));  
  11.             return m ;  
  12.         } else {  
  13.             ModelAndView m = new ModelAndView("login");  
  14.             m.addObject("email", email);  
  15.             m.addObject("password", password);  
  16.             m.addObject("errorMessage""邮箱或者密码不正确");  
  17.             return m;  
  18.         }  
  19.     }  
  20.   
  21.   
  22. 前台清理:  
  23.   
  24. <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
  25.     pageEncoding="ISO-8859-1"%>  
  26. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  27. <html>  
  28. <head>  
  29. <script src="../js/jquery.min.js"></script>  
  30. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
  31. <title>Insert title here</title>  
  32. <script>  
  33.     $(document).ready(function() {  
  34.         localStorage.clear();  
  35.         location.href="/Shop";  
  36.     });  
  37. </script>  
  38. </head>  
  39. <body>  
  40. </body>  
  41. </html>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值