一、购物车的三种实现思路
1.用户未登录时,购物车数据存入Cookie中,登录后,存入Redis中,并且在用户首次登录时判断cookie是否有购物车数据,合并cookie中的数据到redis中,(Cookie最大存放4K)
2.采用LocalStorage解决cookie中数据限制,(一般浏览器是5M,存多了数据页面会变卡)
3.不考虑用户是否登录,都存入Redis中,未登录时随机出一个UUID作为Redis的key,并将该UUID存入Cookie中,用户登录后,从SpringSecurity中获取当前用户名,合并以UUID为key的购物车数据到用户名loginname为key的购物车数据中(开发用到的)
我们使用SpringSecurity整合CAS(单点登陆)技术来实现用户登陆
二、购物车结构的说明

一个用户的购物车List<Cart>里存放着多个Cart(子购物车),每个Cart分为三部分,sellerId(商家ID)、sellerName(公司名称)、orderItemList(购物车商品明细,也就是每一个SKU在购物车中的表现形式!)
购物车Cart这个对象在数据库中并不存在,所以我们在pojo的entity包下建立一个Cart实体类(注意别忘了实现序列化),而TborderItem这个购物车中商品明细存在实体类,所以不必再创建

三、实现了页面初始化展示所有购物车
CartController.java中
展示所有的购物车上来先判断用户是否处于登陆状态,如果登陆就将未登录时购物车中的商品明细和用户的购物车的商品合并在一个购物车中,并且把新的购物车以用户的登录名作为key存到redis中.
合并的原理就:先遍历未登录所有的购物车Cart,再遍历购物车中所有的商品明细,把每一个商品明细通过addItemToCartList()方法加到登陆的购物车中即可
/**
* 查看所有的购物车列表
*
* @return
*/
@RequestMapping("/findCartList")
public List<Cart> findCartList() {
String loginname = SecurityContextHolder.getContext().getAuthentication().getName();
String uuid = getUUid();
//获取未登陆时的购物车
List<Cart> cartList = cartService.findCartListFromRedis(uuid);
if (!"anonymousUser".equals(loginname)) {
//如果是登陆状态
//获取登陆时的购物车
List<Cart> cartListLogin = cartService.findCartListFromRedis(loginname);
if (cartList.size() > 0) {//如果未登陆的购物车里有内容才合并
//将登陆时的购物车和未登陆时的购物车进行合并
List<Cart> mergeCartList = cartService.mergeCartList(cartListLogin, cartList);
//删除未登陆时存在redis中的数据
cartService.removeCartListFromRedis(uuid);
//并且把合并的数据存到redis中
cartService.addCartListToRedis(loginname,mergeCartList);
return mergeCartList;
}else {
//如果未登录的购物车里没有内容,就不用进行合并
return cartListLogin;
}
}
return cartList;
}findCartListFromRedis方法中,如果在service层通过redisTemplate找不到购物车集合(也就是为null时),就自己new一个ArrayList()回来

getUUid()方法就是从Cookie中拿UUID,如果没有就自己随机出一个来并放到Cookie中,Cookie中uuid的存活时间时2天(也就是说2天内不清Cookie,数据一直有),2天之后Cookie中没有数据了,redis中还有,所以也可以在redis中设置一个存活时间,避免redis資源浪费.
/**
* 获取当前cookie中的uuid
*
* @return
*/
public String getUUid() {
String uuid = CookieUtil.getCookieValue(httpServletRequest, "uuid", "utf-8");
if (uuid == null || uuid.equals("")) {
//如果没有当前的cookie中没有uuid,就自己随机出一个
uuid = UUID.randomUUID().toString();
//并且存到当前的cookie中
CookieUtil.setCookie(httpServletRequest, httpServletResponse, "uuid", uuid, 48 * 60 * 60, "utf-8");
}
return uuid;
}CartServiceImpl.java中
/**
* 把新的购物车集合存到redis中
* @param cartList
*/
@Override
public void addCartListToRedis(String uuid,List<Cart> cartList) {
redisTemplate.boundHashOps("cartList").put(uuid,cartList);
}
/**
* 将未登录的购物车和登陆的购物车合并为一个购物车
* @param cartList1
* @param cartList2
* @return
*/
@Override
public List<Cart> mergeCartList(List<Cart> cartList1, List<Cart> cartList2) {
//遍历第一个购物车
for (Cart cart : cartList1) {
//获取每一个购物车里的所有商品
List<TbOrderItem> orderItemList = cart.getOrderItemList();
for (TbOrderItem orderItem : orderItemList) {
//别忘了接收添加后新的购物车
cartList2=addItemToCartList(cartList2,orderItem.getItemId(),orderItem.getNum());
}
}
return cartList2;
}
/**
* 把未登录时购物车的内容从redis中删除
* @param uuid
*
*/
@Override
public void removeCartListFromRedis(String uuid) {
redisTemplate.boundHashOps("cartList").delete(uuid);
}四、实现了购物车添加商品明细
实现思路:其实就是将SKU表(TbItem)的数据转换成TbOrderItem表的数据,并存入到Cart购物车中,并把每一个Cart添加到List<Cast>集合中
这是CartServcie.java中的方法
/**
* 添加商品到购物车列表
*
* @param cartList 当前购物车列表
* @param itemId 添加SKU商品的id
* @param num 添加的数量
* @return 返回添加完商品之后的购物车集合
*/
public List<Cart> addItemToCartList(List<Cart> cartList, Long itemId, Integer num);controller调添加购物车商品明细的方法,需要从redis中获取当前的List<Cart>购物车集合,并把要添加的SKU的id和SKU商品的数量传给service层,返回一个添加完之后的购物车明细表,别忘了把新的购物车明细表添加到reids中还是用原来的uuid,这样就能替换旧的购物车
具体实现方法见代码...