Принцип корзины и реализации Java (имитация Jingdong принцип реализации)

Java задняя часть Java EE
Принцип корзины и реализации Java (имитация Jingdong принцип реализации)

Сегодня начать писать о вещах в корзине, где сначала бросьте четыре вопроса:

1) Пользователь не входит в систему с именем пользователя и паролем, добавляет продукты, закрывает браузер и открывает его снова без входа в систему с именем пользователя и паролем В: Товар в корзине еще доступен? 

2) Пользователь входит в систему с именем пользователя и паролем, добавляет продукты, закрывает браузер и снова открывает его, не входя в систему с именем пользователя и паролем В: Товар в корзине все еще доступен? 

3) Пользователь входит в систему с именем пользователя и паролем, добавляет продукты, закрывает браузер, затем снова открывает его и входит в систему с именем пользователя и паролем В: Товар в корзине все еще доступен?

4) Пользователь входит в систему с именем пользователя и паролем, добавляет товары, закрывает браузер и открывает браузер в родном городе.

Приведенные выше четыре вопроса основаны на JD.com, так что угадайте, каков результат?

1) в

2) ушел

3) в

4) в

Если вы можете угадать ответ, это означает, что вы действительно хороши, так как же вы достигли этих четырех пунктов? (Если вы не согласны, вы можете использовать JD.com для экспериментов)

Далее давайте объясним принцип работы корзины и, наконец, поговорим о конкретной реализации кода.

1) Пользователь не входит в систему и добавляет продукт. В это время продукт добавляется в файл cookie браузера, поэтому, когда пользователь снова посещает (без входа в систему), продукт все еще находится в файле cookie, поэтому продукт в корзина все еще существует.

2) пользователь входит в систему и добавляет продукты. В это время продукты в cookie и продукты, выбранные пользователем, будут добавлены в корзину, а затем продукты в файле cookie будут удалены. Так когда когда пользователь посещает Опять же (без входа в систему), покупки в файле cookie будут удалены элемент тележки, поэтому элемент в корзине уже нет.

3) Пользователь входит в систему и добавляет продукт. В это время продукт добавляется в базу данных для постоянного хранения. После повторного открытия имени пользователя и пароля для входа продукт, выбранный пользователем, должен все еще существовать, поэтому продукт в корзина все еще существует.

4) Причина 3)

Давайте поговорим о преимуществах сохранения продуктов в Cookie без входа в систему и о сравнении сохранения в Session и базе данных:

1: Куки: Преимущества: Сохранить браузер пользователя (без использования сервера нашей компании) Недостатки: Куки отключены, сохранение не предусмотрено

2: Сессия: (Redis: тратит много памяти сервера: внедрить, отключить куки) очень быстро

3: База данных (Mysql, Redis, SOlr) может быть постоянной, скорость базы данных слишком низкая.

Итак, я хочу сказать сегодня:

  • Пользователь не вошел в систему: корзина добавлена ​​в cookie

  • Логин пользователя: сохранить корзину в Redis (без базы данных)

Общая схема идеи:

Далее приведен пример кода для реализации функции корзины:

Во-первых, давайте посмотрим на дизайн двух JavaBean для корзины покупок и товаров для покупок:

Корзина: покупательCart.java

1 public class BuyerCart implements Serializable{
2 
3     /**
4      * 购物车
5      */
6     private static final long serialVersionUID = 1L;
7     
8     //商品结果集
9     private List<BuyerItem> items = new ArrayList<BuyerItem>();
10     
11     //添加购物项到购物车
12     public void addItem(BuyerItem item){
13         //判断是否包含同款
14         if (items.contains(item)) {
15             //追加数量
16             for (BuyerItem buyerItem : items) {
17                 if (buyerItem.equals(item)) {
18                     buyerItem.setAmount(item.getAmount() + buyerItem.getAmount());
19                 }
20             }
21         }else {
22             items.add(item);
23         }
24         
25     }
26 
27     public List<BuyerItem> getItems() {
28         return items;
29     }
30 
31     public void setItems(List<BuyerItem> items) {
32         this.items = items;
33     }
34     
35     
36     //小计
37     //商品数量
38     @JsonIgnore
39     public Integer getProductAmount(){
40         Integer result = 0;
41         //计算
42         for (BuyerItem buyerItem : items) {
43             result += buyerItem.getAmount();
44         }
45         return result;
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, поэтому их нельзя преобразовать, вам нужно использовать ignore 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 (первичный ключ таблицы инвентаря, идентификатор продукта, цвет, размер, инвентарь и другая информация, сохраненная в таблице инвентаря), сумма покупки.

Затем давайте посмотрим, как с этим справится Контроллер:

1 //加入购物车
2     @RequestMapping(value="/shopping/buyerCart")
3     public <T> 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<BuyerItem> items = buyerCart.getItems();
41         Collections.sort(items, new Comparator<BuyerItem>() {
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(24*60*60);
72             //5,Cookie写会浏览器
73             response.addCookie(cookie);
74         }
75         
76         //6, 重定向
77         return "redirect:/shopping/toCart";
78     }

Вот разработанная точка знаний: конвертировать объекты в строки json / строки json в объекты

Сначала мы напишем небольшую демонстрацию, чтобы продемонстрировать взаимное преобразование между json и объектами, используя класс ObjectMapper в springmvc.

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. прочитать значение().
Возвращаясь к коду в нашем проекте выше, этот элемент будет добавлен в файл 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(24*60*60);
11             //5,Cookie写会浏览器
12             response.addCookie(cookie);

Мы отлаживаем видим:

Здесь объект покупательской тележки для покупок был преобразован в формат Json.

Чтобы добавить товар в корзину, независимо от того, вошли вы в систему или нет, вы должны сначала удалить корзину в файле cookie, а затем добавить выбранный в данный момент продукт в корзину.

Затем, если вы войдете в систему, очистите корзину покупок в файле cookie и добавьте содержимое корзины покупок в Redis для постоянного хранения.

Если вы не вошли в систему, добавьте выбранный элемент в файл cookie.

Код для добавления корзины для покупок в redis: insertbuyercarttoreidis (это включает в себя судейство, будет ли добавленный предмет такой же)

1 //保存购物车到Redis中
2     public void insertBuyerCartToRedis(BuyerCart buyerCart, String username){
3         List<BuyerItem> 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. Страница отображения корзины покупок

Наконец, перенаправьте на страницу отображения корзины покупок: верните «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<BuyerItem> 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     }

Вот страница отображения сведений о корзине.Здесь следует отметить, что если один и тот же продукт добавляется постоянно, его необходимо объединить.

Страница отображения сведений о корзине состоит из двух частей: 1) сведения о продукте 2) общая сумма (общий объем товара, стоимость доставки)

1) Информация о продукте также включает размер продукта, цвет продукта, количество покупки продукта и наличие на складе.

Выньте корзину покупок в Redis: buyCart = cartService.selectBuyerCartFromRedis(username);

1     //取出Redis中购物车
2     public BuyerCart selectBuyerCartFromRedis(String username){
3         BuyerCart buyerCart = new BuyerCart();
4         //获取所有商品, redis中保存的是skuId 为key , amount 为value的Map集合
5         Map<String, String> hgetAll = jedis.hgetAll("buyerCart:"+username);
6         Set<Entry<String, String>> entrySet = hgetAll.entrySet();
7         for (Entry<String, String> entry : entrySet) {
8             //entry.getKey(): skuId
9             Sku sku = new Sku();
10             sku.setId(Long.parseLong(entry.getKey()));
11             BuyerItem buyerItem = new BuyerItem();
12             buyerItem.setSku(sku);
13             //entry.getValue(): amount
14             buyerItem.setAmount(Integer.parseInt(entry.getValue()));
15             //添加到购物车中
16             buyerCart.addItem(buyerItem);
17         }
18         
19         return buyerCart;
20     }

Заполните корзину, просто поместите skuId в корзину, и вам нужно узнать детали sku здесь: List items = buyCart.getItems();
buyerItem.setSku(cartService.selectSkuById(buyerItem.getSku().getId()));

1 //向购物车中的购物项 添加相应的数据, 通过skuId 查询sku对象, 颜色对象, 商品对象
2     public Sku selectSkuById(Long skuId){
3         Sku sku = skuDao.selectByPrimaryKey(skuId);
4         //颜色
5         sku.setColor(colorDao.selectByPrimaryKey(sku.getColorId()));
6         //添加商品信息
7         sku.setProduct(productDao.selectByPrimaryKey(sku.getProductId()));
8         return sku;
9     }

Затем вернитесь на «cart.jsp», который является страницей отображения сведений о корзине.

3. Перейдите на страницу оформления заказа

На данный момент это означает, что пользователь должен войти в систему, и в корзине должны быть товары.

Итак, здесь вам нужно использовать функцию фильтрации springmvc.Когда пользователи нажимают поселение, они должны сначала войти в систему.Если они не войдут в систему, им будет предложено войти в систему.

1 //去结算
2     @RequestMapping(value="/buyer/trueBuy")
3     public String trueBuy(String[] skuIds, Model model, HttpServletRequest request, HttpServletResponse response){
4         //1, 购物车必须有商品, 
5         //取出用户名  再取出购物车
6         String username = sessionProviderService.getAttributterForUsername(RequestUtils.getCSessionId(request, response));
7         //取出所有购物车
8         BuyerCart buyerCart = cartService.selectBuyerCartFromRedisBySkuIds(skuIds, username);
9         List<BuyerItem> items = buyerCart.getItems();
10         if (items.size() > 0) {
11             //购物车中有商品
12             //判断所勾选的商品是否都有货, 如果有一件无货, 那么就刷新页面.
13             Boolean flag = true;
14             //2, 购物车中商品必须有库存 且购买大于库存数量时视为无货. 提示: 购物车原页面不动. 有货改为无货, 加红提醒.
15             for (BuyerItem buyerItem : items) {
16                 //装满购物车的购物项, 当前购物项只有skuId这一个东西, 我们还需要购物项的数量去判断是否有货
17                 buyerItem.setSku(cartService.selectSkuById(buyerItem.getSku().getId()));
18                 //校验库存
19                 if (buyerItem.getAmount() > buyerItem.getSku().getStock()) {
20                     //无货
21                     buyerItem.setIsHave(false);
22                     flag = false;
23                 }
24                 if (!flag) {
25                     //无货, 原页面不动, 有货改成无货, 刷新页面.
26                     model.addAttribute("buyerCart", buyerCart);
27                     return "cart";
28                 }
29             }
30         }else {
31             //购物车没有商品
32             //没有商品: 1>原购物车页面刷新(购物车页面提示没有商品)
33             return "redirect:/shopping/toCart";
34         }
35         
36         
37         //3, 正常进入下一个页面
38         return "order";
39     }

Выньте указанную корзину для покупок, потому что мы проверим товары, которые нам нужно купить, на странице сведений о корзине перед расчетом, поэтому здесь мы будем рассчитываться в соответствии с проверенными товарами.
BuyerCart buyerCart = cartService.selectBuyerCartFromRedisBySkuIds(skuIds, username);

Удалить указанный товар из корзины:

1 //从购物车中取出指定商品
2     public BuyerCart selectBuyerCartFromRedisBySkuIds(String[] skuIds, String username){
3         BuyerCart buyerCart = new BuyerCart();
4         //获取所有商品, redis中保存的是skuId 为key , amount 为value的Map集合
5         Map<String, String> hgetAll = jedis.hgetAll("buyerCart:"+username);
6         if (null != hgetAll && hgetAll.size() > 0) {
7             Set<Entry<String, String>> entrySet = hgetAll.entrySet();
8             for (Entry<String, String> entry : entrySet) {
9                 for (String skuId : skuIds) {
10                     if (skuId.equals(entry.getKey())) {
11                         //entry.getKey(): skuId
12                         Sku sku = new Sku();
13                         sku.setId(Long.parseLong(entry.getKey()));
14                         BuyerItem buyerItem = new BuyerItem();
15                         buyerItem.setSku(sku);
16                         //entry.getValue(): amount
17                         buyerItem.setAmount(Integer.parseInt(entry.getValue()));
18                         //添加到购物车中
19                         buyerCart.addItem(buyerItem);
20                     }
21                 }
22             }
23         }
24         
25         return buyerCart;
26     }

1) Если в наличии нет только одного из приобретенных нами товаров, обновите страницу сведений о корзине и повторите статус товара, которого нет в наличии.

2) Когда корзина заполнена в полдень, обновить текущую страницу.

В корзине есть только много вещей. Там могут быть некоторые места, которые не могут быть объяснены или неправильными. Вы можете указать им. Если это полезно для вас, пожалуйста, хотите и поддерживать, спасибо ~