当前位置: 首页 > news >正文

Hash结构之购物车实战

我们平时在网上购物,一般都会有购物车,支持买多件商品,每个商品可以买不同数量。

购物车常见实现方式:

(1)、存储到数据库:性能存在瓶颈。

(2)、后端存储到缓存如redis:支持高性能处理,可以开启AOF持久化防止重启丢失。

购物车数据结构介绍:

购物车结构是一个双层Map,Map<String,Map<String,String>>,第一层Map,Key是用户id;第二层Map,Key是购物车中商品id,值是购物车数据

所以今天我们使用redis的Hash结构来实现购物车,包括添加、查看和清空!

首先我们要准备相关类和数据准备。

VideoDO类:

public class VideoDO {
    private int id;
    private String title;
    private String img;
    private int price;

    public VideoDO() {
    }

    public VideoDO(int id, String title, String img, int price) {
        this.id = id;
        this.title = title;
        this.img = img;
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getImg() {
        return img;
    }

    public void setImg(String img) {
        this.img = img;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}

     CartItemVO类(购物项):

    public class CartItemVO {
        //商品id
        private Integer productId;
    
        //购买数量
        private Integer buyNum;
    
        //商品标题
        private String productTitle;
    
        //图片
        private String productImg;
    
        //商品单价
        private int price ;
    
        //总价格,单价+数量
        private int totalPrice;
    
    
        public int getProductId() {
            return productId;
        }
    
        public void setProductId(int productId) {
            this.productId = productId;
        }
    
        public Integer getBuyNum() {
            return buyNum;
        }
    
        public void setBuyNum(Integer buyNum) {
            this.buyNum = buyNum;
        }
    
        public String getProductTitle() {
            return productTitle;
        }
    
        public void setProductTitle(String productTitle) {
            this.productTitle = productTitle;
        }
    
        public String getProductImg() {
            return productImg;
        }
    
        public void setProductImg(String productImg) {
            this.productImg = productImg;
        }
    
        /**
         * 商品单价 * 购买数量
         * @return
         */
        public int getTotalPrice() {
    
            return this.price*this.buyNum;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    
        public void setTotalPrice(int totalPrice) {
            this.totalPrice = totalPrice;
        }
    }
    

    CartVO类(购物车):

    public class CartVO {
        //购物项
        private List<CartItemVO> cartItems;
    
        //购物车总价格
        private Integer totalAmount;
    
        //总价格
        public int getTotalAmount() {
            return cartItems.stream().mapToInt(CartItemVO::getTotalPrice).sum();
        }
    
        public List<CartItemVO> getCartItems() {
            return cartItems;
        }
    
        public void setCartItems(List<CartItemVO> cartItems) {
            this.cartItems = cartItems;
        }
    }
    

    数据源层(这里我们为了方便实现,我们省略service层):

    @Repository
    public class VideoDao {
        private static Map<Integer, VideoDO> map = new HashMap<>();
    
        static {
            map.put(1,new VideoDO(1,"综合项目实战","hhhh",1000));
            map.put(2,new VideoDO(2,"RabbitMQ实战","llll",479));
            map.put(3,new VideoDO(3,"Java基础","xxxx",449));
            map.put(4,new VideoDO(4,"玩转Nginx","yyyy",549));
            map.put(5,new VideoDO(5,"ssm课程","oooo",649));
            map.put(6,new VideoDO(6,"SpringCloud实战","zzzz",559));
        }
    
        
         // 模拟从数据库找
        public VideoDO findDetailById(int videoId) {
            return map.get(videoId);
        }
    }
    

    json工具类:

    public class JsonUtil {
        // 定义jackson对象
        private static final ObjectMapper MAPPER = new ObjectMapper();
    
        /**
         * 将对象转换成json字符串。
    
         * @return
         */
        public static String objectToJson(Object data) {
            try {
                String string = MAPPER.writeValueAsString(data);
                return string;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 将json结果集转化为对象
         * @param jsonData json数据
         * @param beanType 对象中的object类型
         * @return
         * @param <T>
         */
        public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
            try {
                T t = MAPPER.readValue(jsonData, beanType);
                return t;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    准备工作做好啦,下面我们来实现添加购物车接口的开发:

    @RestController
    @RequestMapping("/api/v1/cart")
    public class CartController {
        @Autowired
        private RedisTemplate redisTemplate;
        @Autowired
        private VideoDao videoDao;
        @RequestMapping("add")
        //一般我们添加购物车需要商品的id和购买的数量
        public JsonData addCart(int videoId,int buyNum){
            //获取购物车
            BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
            //+“”是为了将videoId变成字符串
            Object cacheObj = myCart.get(videoId+"");
    
            //购物车没有这个商品
            if(cacheObj == null){
                CartItemVO cartItemVO = new CartItemVO();
                VideoDO videoDO = videoDao.findDetailById(videoId);
    
                cartItemVO.setBuyNum(buyNum);
                cartItemVO.setProductId(videoId);
                cartItemVO.setPrice(videoDO.getPrice());
                cartItemVO.setProductImg(videoDO.getImg());
                cartItemVO.setProductTitle(videoDO.getTitle());
    
                myCart.put(videoId+"", JsonUtil.objectToJson(cartItemVO));
            }else {
                //购物车有这个商品,增加商品购买数量
                String result = (String) cacheObj;
                CartItemVO cartItemVO = JsonUtil.jsonToPojo(result, CartItemVO.class);
                cartItemVO.setBuyNum(cartItemVO.getBuyNum()+buyNum);
                myCart.put(videoId+"", JsonUtil.objectToJson(cartItemVO));
            }
            return JsonData.buildSuccess();
    
        }
    
    
        // 抽取我的购物车通用方法
        private BoundHashOperations<String,Object,Object> getMyCartOps(){
            String key = getCartKey();
            return redisTemplate.boundHashOps(key);
        }
    
    
        //获取购物车的key
        private String getCartKey(){
            //用户的id,一般从拦截器获取,这里为了方便,写死即可,每个用户不一样
            int userId = 66;
            String cartKey = String.format("video:cart:%s",userId);
            return cartKey;
        }
    }
    

    我们去浏览器输入http://localhost:8080/api/v1/cart/add?videoId=1&buyNum=2,我们可以去redis可视化查看到视频商品id是1的,购买数量是2件,总价格是2000。

    我们再次访问http://localhost:8080/api/v1/cart/add?videoId=1&buyNum=2这个网址,视频商品id是1的,购买数量变成4件,总价格变成4000。

    下面我们就来实现查看我的购物车接口开发:

    /**
         * 查看我的购物车
         * @return
         */
        @RequestMapping("myCart")
        public JsonData getMyCart(){
            //获取购物车
            BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
            List<Object> itemList = myCart.values();
            List<CartItemVO> cartItemVOList = new ArrayList<>();
            for(Object item : itemList){
                CartItemVO cartItemVO = JsonUtil.jsonToPojo((String) item,CartItemVO.class);
                cartItemVOList.add(cartItemVO);
            }
            CartVO cartVO = new CartVO();
            cartVO.setCartItems(cartItemVOList);
            return JsonData.buildSuccess(cartVO);
        }

    当我们去访问该接口时,就可以查询到我的购物车有什么商品。

     

    最后我们来开发一下清空购物车:

    /**
         * 清空我的购物车
         * @return
         */
        @RequestMapping("clear")
        public JsonData clear(){
            String key = getCartKey();
            redisTemplate.delete(key);
            return JsonData.buildSuccess();
        }

     清空购物车之后查看我的购物车就是空的。

     

     

     

     

     

     

    http://www.dtcms.com/a/112968.html

    相关文章:

  • 【零基础入门unity游戏开发——动画篇】unity旧动画系统Animation组件的使用
  • AntDesign下,Select内嵌Menu标签,做一个多选下拉框,既可以搜索,还可以选择下拉项
  • 【项目管理】第一部分 信息技术 1/2
  • 十道海量数据处理面试题与十个方法总结
  • 嵌入式Linux驱动—— 1 GPIO配置
  • 浙考!【触发器逻辑方程推导(电位运算)】
  • Ai提示词大师 1.0 | 预制1000+模板满足
  • 《Java实战:素数检测算法优化全解析——从暴力枚举到筛法进阶》
  • GD32H759IMT6 Cortex-M7 OpenHarmony轻量系统移植——4.1版本升级到5.0.3
  • 网络编程—TCP/IP模型(UDP协议与自定义协议)
  • Altshuller矛盾矩阵查询:基于python和streamlit
  • 哈希表(Hashtable)核心知识点详解
  • 【虚拟仪器技术】Labview虚拟仪器技术习题答案(二),设计VI程序
  • 练习题:124
  • Java Web从入门到精通:全面探索与实战(一)
  • 基于YOLO11实例分割与奥比中光相机的快递包裹抓取点检测
  • 基于CATIA产品结构树智能排序的二次开发技术解析——深度定制BOM层级管理系统的Pycatia实践
  • docker搭建minio集群(简化版)
  • MessageQueue --- RabbitMQ WorkQueue
  • Redis-Hash类型
  • 我的购物车设计思考:从个人项目到生产实战思考的蜕变
  • 【Linux网络与网络编程】05.应用层自定义协议序列化和反序列化
  • Systemd构建自动化备份服务与外部存储管理
  • KAPC的前世今生--(下)下RPCRT4!NMP_SyncSendRecv函数分析
  • 去中心化指数(链上ETF)
  • 【小沐学Web3D】three.js 加载三维模型(React Three Fiber)
  • Cribl 通过Generic API新建 Dataset
  • 谈谈策略模式,策略模式的适用场景是什么?
  • 基本机动飞行性能
  • 车辆信息查询API——车辆车五项查询