首页 > 其他分享 >商城项目改进购物车防止下单的幂等性问题-----商城项目

商城项目改进购物车防止下单的幂等性问题-----商城项目

时间:2024-09-23 22:21:26浏览次数:3  
标签:skuId CartItem cartItem cart 购物车 ----- import com 商城

package com.alatus.mall.cart.web;

import com.alatus.mall.cart.service.CartService;
import com.alatus.mall.cart.vo.CartItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.concurrent.ExecutionException;

@Controller
public class CartController {
    @Autowired
    private CartService cartService;
    @GetMapping("/cart.html")
    public String cartListPage(){
        return "cartList";
    }
    @GetMapping("/addToCart")
    public String addToCart(@RequestParam("skuId") Long skuId, @RequestParam("num") Integer num, RedirectAttributes model) throws ExecutionException, InterruptedException {
        if(num > 0){
            CartItem cartItem = cartService.addToCart(skuId,num);
            model.addAttribute("skuId",skuId);
            return "redirect:http://cart.alatusmall.com/addToCartSuccess.html";
        }
        return "redirect:http://cart.alatusmall.com/addToCartSuccess.html";
    }
    @GetMapping("/addToCartSuccess.html")
    public String addToCartSuccessPage(@RequestParam("skuId")Long skuId,Model model){
        CartItem cartItem = cartService.getCartItem(skuId);
        model.addAttribute("item",cartItem);
        return "success";
    }
}
package com.alatus.mall.cart.web;

import com.alatus.mall.cart.service.CartService;
import com.alatus.mall.cart.vo.CartItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.util.concurrent.ExecutionException;

@Controller
public class CartController {
    @Autowired
    private CartService cartService;
    @GetMapping("/cart.html")
    public String cartListPage(){
        return "cartList";
    }
    @GetMapping("/addToCart")
    public String addToCart(@RequestParam("skuId") Long skuId, @RequestParam("num") Integer num, RedirectAttributes model) throws ExecutionException, InterruptedException {
        if(num > 0){
            CartItem cartItem = cartService.addToCart(skuId,num);
            model.addAttribute("skuId",skuId);
            return "redirect:http://cart.alatusmall.com/addToCartSuccess.html";
        }
        return "redirect:http://cart.alatusmall.com/addToCartSuccess.html";
    }
    @GetMapping("/addToCartSuccess.html")
    public String addToCartSuccessPage(@RequestParam("skuId")Long skuId,Model model){
        CartItem cartItem = cartService.getCartItem(skuId);
        model.addAttribute("item",cartItem);
        return "success";
    }
}
package com.alatus.mall.cart.service;

import com.alatus.mall.cart.vo.CartItem;

import java.util.concurrent.ExecutionException;

public interface CartService {
    CartItem addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException;

    CartItem getCartItem(Long skuId);
}
package com.alatus.mall.cart.service;

import com.alatus.mall.cart.vo.CartItem;

import java.util.concurrent.ExecutionException;

public interface CartService {
    CartItem addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException;

    CartItem getCartItem(Long skuId);
}
package com.alatus.mall.cart.service.impl;

import com.alatus.common.utils.R;
import com.alatus.mall.cart.feign.ProductFeignService;
import com.alatus.mall.cart.service.CartService;
import com.alatus.mall.cart.vo.CartItem;
import com.alatus.mall.cart.vo.SkuInfoVo;
import com.alatus.mall.cart.vo.UserInfoTo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.alatus.mall.cart.interceptor.CartInterceptor;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ProductFeignService productFeignService;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    private final String CART_PREFIX = "alatusmall:cart:";
    @Override
    public CartItem addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String res = (String) cartOps.get(skuId.toString());
        if(StringUtils.isEmpty(res)){
            CartItem cartItem = new CartItem();
//            当购物车没有该商品
//        查询商品服务目前添加的商品信息
            CompletableFuture<Void> getSkuInfo = CompletableFuture.runAsync(() -> {
                R info = productFeignService.info(skuId);
                if (info.getCode() == 0) {
                    SkuInfoVo skuInfo = info.get("skuInfo", new TypeReference<SkuInfoVo>() {});
                    cartItem.setCheck(true);
                    cartItem.setCount(num);
                    cartItem.setImage(skuInfo.getSkuDefaultImg());
                    cartItem.setTitle(skuInfo.getSkuTitle());
                    cartItem.setSkuId(skuId);
                    cartItem.setPrice(skuInfo.getPrice());
                }
            }, threadPoolExecutor);
            CompletableFuture<Void> getSkuAttrValues = CompletableFuture.runAsync(() -> {
//            远程查询sku的组合信息
                List<String> skuSaleAttrValues = productFeignService.getSkuSaleAttrValues(skuId);
                cartItem.setSkuAttr(skuSaleAttrValues);
            }, threadPoolExecutor);
            CompletableFuture.allOf(getSkuInfo,getSkuAttrValues).get();
            String jsonString = JSON.toJSONString(cartItem);
            cartOps.put(skuId.toString(),jsonString);
            return cartItem;
        }
        else{
//            购物车有这个商品
            CartItem oldCartItem = JSON.parseObject(res, CartItem.class);
            oldCartItem.setCount(oldCartItem.getCount()+num);
            cartOps.put(skuId.toString(),JSON.toJSONString(oldCartItem));
            return oldCartItem;
        }
    }

    @Override
    public CartItem getCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String res = (String)cartOps.get(skuId.toString());
        return JSON.parseObject(res, CartItem.class);
    }

    //    获取我们要操作的购物车
    private BoundHashOperations<String, Object, Object> getCartOps(){
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
//        用户已登录
        String cartKey = "";
        if(userInfoTo.getUserId()!=null){
            cartKey = CART_PREFIX + userInfoTo.getUserId();
        }
//        用户未登录
        else{
            cartKey = CART_PREFIX + userInfoTo.getUserKey();
        }
        BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(cartKey);
        return operations;
    }
}
package com.alatus.mall.cart.service.impl;

import com.alatus.common.utils.R;
import com.alatus.mall.cart.feign.ProductFeignService;
import com.alatus.mall.cart.service.CartService;
import com.alatus.mall.cart.vo.CartItem;
import com.alatus.mall.cart.vo.SkuInfoVo;
import com.alatus.mall.cart.vo.UserInfoTo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.alatus.mall.cart.interceptor.CartInterceptor;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ProductFeignService productFeignService;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    private final String CART_PREFIX = "alatusmall:cart:";
    @Override
    public CartItem addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String res = (String) cartOps.get(skuId.toString());
        if(StringUtils.isEmpty(res)){
            CartItem cartItem = new CartItem();
//            当购物车没有该商品
//        查询商品服务目前添加的商品信息
            CompletableFuture<Void> getSkuInfo = CompletableFuture.runAsync(() -> {
                R info = productFeignService.info(skuId);
                if (info.getCode() == 0) {
                    SkuInfoVo skuInfo = info.get("skuInfo", new TypeReference<SkuInfoVo>() {});
                    cartItem.setCheck(true);
                    cartItem.setCount(num);
                    cartItem.setImage(skuInfo.getSkuDefaultImg());
                    cartItem.setTitle(skuInfo.getSkuTitle());
                    cartItem.setSkuId(skuId);
                    cartItem.setPrice(skuInfo.getPrice());
                }
            }, threadPoolExecutor);
            CompletableFuture<Void> getSkuAttrValues = CompletableFuture.runAsync(() -> {
//            远程查询sku的组合信息
                List<String> skuSaleAttrValues = productFeignService.getSkuSaleAttrValues(skuId);
                cartItem.setSkuAttr(skuSaleAttrValues);
            }, threadPoolExecutor);
            CompletableFuture.allOf(getSkuInfo,getSkuAttrValues).get();
            String jsonString = JSON.toJSONString(cartItem);
            cartOps.put(skuId.toString(),jsonString);
            return cartItem;
        }
        else{
//            购物车有这个商品
            CartItem oldCartItem = JSON.parseObject(res, CartItem.class);
            oldCartItem.setCount(oldCartItem.getCount()+num);
            cartOps.put(skuId.toString(),JSON.toJSONString(oldCartItem));
            return oldCartItem;
        }
    }

    @Override
    public CartItem getCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String res = (String)cartOps.get(skuId.toString());
        return JSON.parseObject(res, CartItem.class);
    }

    //    获取我们要操作的购物车
    private BoundHashOperations<String, Object, Object> getCartOps(){
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
//        用户已登录
        String cartKey = "";
        if(userInfoTo.getUserId()!=null){
            cartKey = CART_PREFIX + userInfoTo.getUserId();
        }
//        用户未登录
        else{
            cartKey = CART_PREFIX + userInfoTo.getUserKey();
        }
        BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(cartKey);
        return operations;
    }
}

标签:skuId,CartItem,cartItem,cart,购物车,-----,import,com,商城
From: https://blog.csdn.net/2201_75960169/article/details/142470236

相关文章

  • 密码学承诺原理与应用 - 概览
    作者:@warm3snowhttps://github.com/warm3snow微信公众号:密码应用技术实战博客园首页:https://www.cnblogs.com/informatics/标签:技术分享模板目录简介承诺方案原理符号定义方案定义常见承诺方案和原理哈希承诺ElGamal承诺Pedersen承诺零知识证明承诺Sigma承诺Sigma承诺正确......
  • 所有协议合集--(2)
    1.PPP(点到点协议):官方定义:一种在点到点链路上传输多协议数据包的数据链路层协议。用途:主要用于在串行线路上建立连接,如拨号上网、路由器之间的连接等。数据结构:PPP帧由标志字段、地址字段、控制字段、协议字段、信息字段和帧校验序列字段组成。学习网站及网址:“RFC文档”:htt......
  • 题解:CF888G Xor-MST
    题解:CF888GXor-MST题目大意:给定\(n\)个点的点权,任意两点间边权是点权的异或和。求这张完全图的MST的权值。思路:Boruvka+Trie树+按位贪心。关键就在于如何求出Boruvka中的best数组。考虑对点权建trie树,对于节点\(i\)本轮的连边,就是找“和它最相似”的那......
  • RHCS认证-Linux(RHel9)-Ansible
    文章目录一、ansible简介二、ansible部署三、ansible服务端测试四、ansible清单inventory五、Ad-hot点对点模式六、YAML语言模式七、RHCS-Ansible附:安装CentOS-Stream9系统7.1ansible执行过程7.2安装ansible,ansible-navigator7.2部署ansible7.3ansible-naviga......
  • roslaunch carla_ros_bridge carla_ros_bridge.launch运行报错逐条解决REQUIREDproces
    前言:跟着自动驾驶之心的老师学习仿真,在carla_ros_bridge那块卡住了,遇到了超多问题,现在看看我们是怎么解决的吧。首先是carla_ros_bridge安装,老师是18.04,我的项目工程是20.04,所以我肯定最终还是要换到20.04的,所以以下就是踩坑。一.carla_ros_bridge安装:可见官网的文档ROSbri......
  • FreeMarker 禁止自动转义标签-noautoesc
    ......
  • 夜王 - section1 - 萦平
    引子“夜王?什么夜王?那个晚上街头唱歌的”?“不是啊……是DOTA游戏里面那个夜王”。——这是立子第一次听说“夜王”这个称号,这个名词,原本他总觉得在哪听过,现在想起来了,原来是阿超高中时跟他提起过。section1萦平萦平县坐落在我国西北方,属于前邱市的下的一个小县城,县城里唯二......
  • SP1825 FTOUR2 - Free tour II 题解
    题目传送门前置知识点分治|树状数组解法维护点对信息,考虑点分治。本题比luoguP4149[IOI2011]Race多了个前缀查询\(\max\)。套个支持单点修改、区间查询\(\max\)的数据结构即可。直接线段树维护区间\(\max\)貌似会TLE,换成树状数组维护前缀\(\max\)即可。注......
  • d2l-ai深度学习日记(一)
    前言:这个博客《d2l-ai深度学习日记》将记录我在深度学习领域的学习与探索,特别是基于《动手学深度学习》这本经典教材的学习过程。在这个过程中,我不仅希望总结所学,还希望通过分享心得,与志同道合的朋友一起交流成长。这不仅是对知识的沉淀,也是我备战研究生考试、追逐学术进阶之......
  • d2l-ai深度学习日记之预备知识(一)
     引言        笔者目前在大三阶段,想跟着研究生老师学习,以便创造更多的深造机会,故学习深度学习.我使用教材d2l-zh进行学习.这篇文章主要是学习预备知识.在此之前,我已经有了python等语言的基本基础.这个博客《d2l-ai深度学习日记》将记录我在深度学习领域的学习与......