购物车的原理及Java实现(仿京东实现原理)

46     }

47

48     //商品金额

49     @JsonIgnore

50     public Float getProductPrice(){

51         Float result = 0f;

52         //计算

53         for (BuyerItem buyerItem : items) {

54             result += buyerItem.getAmount()*buyerItem.getSku().getPrice();

55         }

56         return result;

57     }

58

59     //运费

60     @JsonIgnore

61     public Float getFee(){

62         Float result = 0f;

63         //计算

64         if (getProductPrice() < 79) {

65             result = 5f;

66         }

67

68         return result;

69     }

70

71     //总价

72     @JsonIgnore

73     public Float getTotalPrice(){

74         return getProductPrice() + getFee();

75     }

76

77 }

这里使用了@JsonIgonre注解是因为下面需要将BuyerCart 转换成Json格式, 而这几个字段只有get 方法, 所以不能转换, 需要使用忽略Json.

下面是购物项: buyerItem.java

1 public class BuyerItem implements Serializable{

2

3     private static final long serialVersionUID = 1L;

4

5     //SKu对象

6     private Sku sku;

7

8     //是否有货

9     private Boolean isHave = true;

10

11     //购买的数量

12     private Integer amount = 1;

13

14     public Sku getSku() {

15         return sku;

16     }

17

18     public void setSku(Sku sku) {

19         this.sku = sku;

20     }

21

22     public Boolean getIsHave() {

23         return isHave;

24     }

25

26     public void setIsHave(Boolean isHave) {

27         this.isHave = isHave;

28     }

29

30     public Integer getAmount() {

31         return amount;

32     }

33

34     public void setAmount(Integer amount) {

35         this.amount = amount;

36     }

37

38     @Override

39     public int hashCode() {

40         final int prime = 31;

41         int result = 1;

42         result = prime * result + ((sku == null) ? 0 : sku.hashCode());

43         return result;

44     }

45

46     @Override

47     public boolean equals(Object obj) {

48         if (this == obj) //比较地址

49             return true;

50         if (obj == null)

51             return false;

52         if (getClass() != obj.getClass())

53             return false;

54         BuyerItem other = (BuyerItem) obj;

55         if (sku == null) {

56             if (other.sku != null)

57                 return false;

58         } else if (!sku.getId().equals(other.sku.getId()))

59             return false;

60         return true;

61     }

62 }

1、将商品加入购物车中

1 //加入购物车

2 function  addCart(){

3       //  + skuId

4       window.location.href=“/shopping/buyerCart?skuId=”+skuId+“&amount=”+$(“#buy-num”).val();

5 }

这里传入的参数是skuId(库存表的主键, 库存表保存的商品id,颜色,尺码,库存等信息), 购买数量amount.

接着我们来看Controller是如何来处理的:

1 //加入购物车

2     @RequestMapping(value=“/shopping/buyerCart”)

3     public  String buyerCart(Long skuId, Integer amount, HttpServletRequest request,

4             HttpServletResponse response) throws JsonParseException, JsonMappingException, IOException{

5         //将对象转换成json字符串/json字符串转成对象

6         ObjectMapper om = new ObjectMapper();

7         om.setSerializationInclusion(Include.NON_NULL);

8         BuyerCart buyerCart = null;

9         //1,获取Cookie中的购物车

10         Cookie[] cookies = request.getCookies();

11         if (null != cookies && cookies.length > 0) {

12             for (Cookie cookie : cookies) {

13                 //

14                 if (Constants.BUYER_CART.equals(cookie.getName())) {

15                     //购物车 对象 与json字符串互转

16                     buyerCart = om.readValue(cookie.getValue(), BuyerCart.class);

17                     break;

18                 }

19             }

20         }

21

22         //2,Cookie中没有购物车, 创建购物车对象

23         if (null == buyerCart) {

24             buyerCart = new BuyerCart();

25         }

26

27         //3, 将当前款商品追加到购物车

28         if (null != skuId && null != amount) {

29             Sku sku = new Sku();

30             sku.setId(skuId);

31             BuyerItem buyerItem = new BuyerItem();

32             buyerItem.setSku(sku);

33             //设置数量

34             buyerItem.setAmount(amount);

35             //添加购物项到购物车

36             buyerCart.addItem(buyerItem);

37         }

38

39         //排序  倒序

40         List items = buyerCart.getItems();

41         Collections.sort(items, new Comparator() {

42

43             @Override

44             public int compare(BuyerItem o1, BuyerItem o2) {

45                 return -1;

46             }

47

48         });

49

50         //前三点 登录和非登录做的是一样的操作, 在第四点需要判断

51         String username = sessionProviderService.getAttributterForUsername(RequestUtils.getCSessionId(request, response));

52         if (null != username) {

53             //登录了

54             //4, 将购物车追加到Redis中

55             cartService.insertBuyerCartToRedis(buyerCart, username);

56             //5, 清空Cookie 设置存活时间为0, 立马销毁

57             Cookie cookie = new Cookie(Constants.BUYER_CART, null);

58             cookie.setPath(“/”);

59             cookie.setMaxAge(-0);

60             response.addCookie(cookie);

61         }else {

62             //未登录

63             //4, 保存购物车到Cookie中

64             //将对象转换成json格式

65             Writer w = new StringWriter();

66             om.writeValue(w, buyerCart);

67             Cookie cookie = new Cookie(Constants.BUYER_CART, w.toString());

68             //设置path是可以共享cookie

69             cookie.setPath(“/”);

70             //设置Cookie过期时间: -1 表示关闭浏览器失效  0: 立即失效  >0: 单位是秒, 多少秒后失效

71             cookie.setMaxAge(246060);

72             //5,Cookie写会浏览器

73             response.addCookie(cookie);

74         }

75

76         //6, 重定向

77         return “redirect:/shopping/toCart”;

78     }

这里设计一个知识点: 将对象转换成json字符串/json字符串转成对象

我们在这里先写一个小的Demo来演示json和对象之间的互转, 这里使用到了springmvc中的ObjectMapper类.

1 public class TestJson {

2

3     @Test

4     public void testAdd() throws Exception {

5         TestTb testTb = new TestTb();

6         testTb.setName(“范冰冰”);

7         ObjectMapper om = new ObjectMapper();

8         om.setSerializationInclusion(Include.NON_NULL);

9         //将对象转换成json字符串

10         Writer wr = new StringWriter();

11         om.writeValue(wr, testTb);

12         System.out.println(wr.toString());

13

14         //转回对象

15         TestTb r = om.readValue(wr.toString(), TestTb.class);

16         System.out.println(r.toString());

17     }

18

19 }

执行结果:

这里我们使用了Include.NON_NULL, 如果TestTb 中属性为null 的就不给转换成Json, 从对象–>Json字符串  用的是 objectMapper.writeValue(). 从Json字符串–>对象使用的是objectMapper.readValue().

回归上面我们项目中的代码, 只有未登录 添加商品时才会将此商品添加到Cookie中.

1 //未登录

2             //4, 保存购物车到Cookie中

3             //将对象转换成json格式

4             Writer w = new StringWriter();

5             om.writeValue(w, buyerCart);

6             Cookie cookie = new Cookie(Constants.BUYER_CART, w.toString());

7             //设置path是可以共享cookie

8             cookie.setPath(“/”);

9             //设置Cookie过期时间: -1 表示关闭浏览器失效  0: 立即失效  >0: 单位是秒, 多少秒后失效

10             cookie.setMaxAge(246060);

11             //5,Cookie写会浏览器

12             response.addCookie(cookie);

我们debug 可以看到:

这里已经将对象购物车对象buyerCart转换成了Json格式.

将商品添加到购物车, 不管是登录还是未登录, 都要先取出Cookie中的购物车, 然后将当前选择的商品追加到购物车中.

然后登录的话  就把Cookie中的购物车清空, 并将购物车的内容添加到Redis中做持久化保存.

如果未登录, 将选择的商品追加到Cookie中.

将购物车追加到Redis中的代码:insertBuyerCartToRedis(这里面包含了判断添加的是否是同款)

1 //保存购物车到Redis中

2     public void insertBuyerCartToRedis(BuyerCart buyerCart, String username){

3         List items = buyerCart.getItems();

4         if (items.size() > 0) {

5             //redis中保存的是skuId 为key , amount 为value的Map集合

6             Map<String, String> hash = new HashMap<String, String>();

7             for (BuyerItem item : items) {

8                 //判断是否有同款

9                 if (jedis.hexists(“buyerCart:”+username, String.valueOf(item.getSku().getId()))) {

10                     jedis.hincrBy(“buyerCart:”+username, String.valueOf(item.getSku().getId()), item.getAmount());

11                 }else {

12                     hash.put(String.valueOf(item.getSku().getId()), String.valueOf(item.getAmount()));

13                 }

14             }

15             if (hash.size() > 0) {

16                 jedis.hmset(“buyerCart:”+username, hash);

17             }

18         }

19

20     }

判断用户是否登录: String username = sessionProviderService.getAttributterForUsername(RequestUtils.getCSessionId(request, response));

1 public class RequestUtils {

2

3     //获取CSessionID

4     public static String getCSessionId(HttpServletRequest request, HttpServletResponse response){

5         //1, 从Request中取Cookie

6         Cookie[] cookies = request.getCookies();

7         //2, 从Cookie数据中遍历查找, 并取CSessionID

8         if (null != cookies && cookies.length > 0) {

9             for (Cookie cookie : cookies) {

10                 if (“CSESSIONID”.equals(cookie.getName())) {

11                     //有, 直接返回

12                     return cookie.getValue();

13                 }

14             }

15         }

16         //没有, 创建一个CSessionId, 并且放到Cookie再返回浏览器.返回新的CSessionID

17         String csessionid = UUID.randomUUID().toString().replaceAll(“-”, “”);

18         //并且放到Cookie中

19         Cookie cookie = new Cookie(“CSESSIONID”, csessionid);

20         //cookie  每次都带来, 设置路径

21         cookie.setPath(“/”);

22         //0:关闭浏览器  销毁cookie. 0:立即消失.  >0 存活时间,秒

23         cookie.setMaxAge(-1);

24

25         return csessionid;

26     }

27 }

1 //获取

2     public String getAttributterForUsername(String jessionId){

3         String value = jedis.get(jessionId + “:USER_NAME”);

4         if(null != value){

5             //计算session过期时间是 用户最后一次请求开始计时.

6             jedis.expire(jessionId + “:USER_NAME”, 60*exp);

7             return value;

8         }

9         return null;

10     }

2、购物车展示页面

最后 重定向到购物车展示页: return “redirect:/shopping/toCart”; 这里进入结算页有两种方式:

  1. 在商品详情页 点击加入购物车.

  2. 直接点击购物车按钮 进入购物车结算页.

下面来看下结算页的代码:

1 @Autowired

2     private CartService cartService;

3     //去购物车结算, 这里有两个地方可以直达: 1,在商品详情页 中点击加入购物车按钮  2, 直接点击购物车按钮

4     @RequestMapping(value=“/shopping/toCart”)

5     public String toCart(Model model, HttpServletRequest request,

6             HttpServletResponse response) throws JsonParseException, JsonMappingException, IOException{

7         //将对象转换成json字符串/json字符串转成对象

8         ObjectMapper om = new ObjectMapper();

9         om.setSerializationInclusion(Include.NON_NULL);

10         BuyerCart buyerCart = null;

11         //1,获取Cookie中的购物车

12         Cookie[] cookies = request.getCookies();

13         if (null != cookies && cookies.length > 0) {

14             for (Cookie cookie : cookies) {

15                 //

16                 if (Constants.BUYER_CART.equals(cookie.getName())) {

17                     //购物车 对象 与json字符串互转

18                     buyerCart = om.readValue(cookie.getValue(), BuyerCart.class);

19                     break;

20                 }

21             }

22         }

23

24         //判断是否登录

25         String username = sessionProviderService.getAttributterForUsername(RequestUtils.getCSessionId(request, response));

26         if (null != username) {

27             //登录了

28             //2, 购物车 有东西, 则将购物车的东西保存到Redis中

29             if (null == buyerCart) {

30                 cartService.insertBuyerCartToRedis(buyerCart, username);

31                 //清空Cookie 设置存活时间为0, 立马销毁

32                 Cookie cookie = new Cookie(Constants.BUYER_CART, null);

33                 cookie.setPath(“/”);

34                 cookie.setMaxAge(-0);

35                 response.addCookie(cookie);

36             }

37             //3, 取出Redis中的购物车

38             buyerCart = cartService.selectBuyerCartFromRedis(username);

39         }

40

41

42         //4, 没有 则创建购物车

43         if (null == buyerCart) {

44             buyerCart = new BuyerCart();

45         }

46

47         //5, 将购物车装满, 前面只是将skuId装进购物车, 这里还需要查出sku详情

48         List items = buyerCart.getItems();

49         if(items.size() > 0){

50             //只有购物车中有购物项, 才可以将sku相关信息加入到购物项中

51             for (BuyerItem buyerItem : items) {

52                 buyerItem.setSku(cartService.selectSkuById(buyerItem.getSku().getId()));

53             }

54         }

55

56         //5,上面已经将购物车装满了, 这里直接回显页面

57         model.addAttribute(“buyerCart”, buyerCart);

58

59         //跳转购物页面

60         return “cart”;

61     }

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

装满, 前面只是将skuId装进购物车, 这里还需要查出sku详情

48         List items = buyerCart.getItems();

49         if(items.size() > 0){

50             //只有购物车中有购物项, 才可以将sku相关信息加入到购物项中

51             for (BuyerItem buyerItem : items) {

52                 buyerItem.setSku(cartService.selectSkuById(buyerItem.getSku().getId()));

53             }

54         }

55

56         //5,上面已经将购物车装满了, 这里直接回显页面

57         model.addAttribute(“buyerCart”, buyerCart);

58

59         //跳转购物页面

60         return “cart”;

61     }

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

[外链图片转存中…(img-JANVNGxx-1714801926695)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值