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

SpringBoot + redis处理购物车逻辑

1、pom.xml

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

2、application.xml

spring:
characterEncoding=utf-8&useSSL=falseredis:host: 127.0.0.1port: 6379

3、CartServiceImpl.java

@Service
public class CartServiceImpl implements ICartService {private final static String CART_REDIS_KEY_TEMPLATE = "cart_%d";@Autowiredprivate ProductMapper productMapper;@Autowiredprivate StringRedisTemplate redisTemplate;private Gson gson = new Gson();@Overridepublic ResponseVo<CartVo> add(Integer uid, CartAddForm form) {Integer quantity = 1;Product product = productMapper.selectByPrimaryKey(form.getProductId());//商品是否存在if (product == null) {return ResponseVo.error(ResponseEnum.PRODUCT_NOT_EXIST);}//商品是否正常在售if (!product.getStatus().equals(ProductStatusEnum.ON_SALE.getCode())) {return ResponseVo.error(ResponseEnum.PRODUCT_OFF_SALE_OR_DELETE);}//商品库存是否充足if (product.getStock() <= 0) {return ResponseVo.error(ResponseEnum.PROODUCT_STOCK_ERROR);}//写入到redis//key: cart_1HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();String redisKey  = String.format(CART_REDIS_KEY_TEMPLATE, uid);Cart cart;String value = opsForHash.get(redisKey, String.valueOf(product.getId()));if (StringUtils.isEmpty(value)) {//没有该商品, 新增cart = new Cart(product.getId(), quantity, form.getSelected());}else {//已经有了,数量+1cart = gson.fromJson(value, Cart.class);cart.setQuantity(cart.getQuantity() + quantity);}opsForHash.put(redisKey,String.valueOf(product.getId()),gson.toJson(cart));return list(uid);}@Overridepublic ResponseVo<CartVo> list(Integer uid) {HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();String redisKey  = String.format(CART_REDIS_KEY_TEMPLATE, uid);Map<String, String> entries = opsForHash.entries(redisKey);boolean selectAll = true;Integer cartTotalQuantity = 0;BigDecimal cartTotalPrice = BigDecimal.ZERO;CartVo cartVo = new CartVo();List<CartProductVo> cartProductVoList = new ArrayList<>();for (Map.Entry<String, String> entry : entries.entrySet()) {Integer productId = Integer.valueOf(entry.getKey());Cart cart = gson.fromJson(entry.getValue(), Cart.class);//TODO 需要优化,使用mysql里的inProduct product = productMapper.selectByPrimaryKey(productId);if (product != null) {CartProductVo cartProductVo = new CartProductVo(productId,cart.getQuantity(),product.getName(),product.getSubtitle(),product.getMainImage(),product.getPrice(),product.getStatus(),product.getPrice().multiply(BigDecimal.valueOf(cart.getQuantity())),product.getStock(),cart.getProductSelected());cartProductVoList.add(cartProductVo);if (!cart.getProductSelected()) {selectAll = false;}//计算总价(只计算选中的)if (cart.getProductSelected()) {cartTotalPrice = cartTotalPrice.add(cartProductVo.getProductTotalPrice());}}cartTotalQuantity += cart.getQuantity();}//有一个没有选中,就不叫全选cartVo.setSelectedAll(selectAll);cartVo.setCartTotalQuantity(cartTotalQuantity);cartVo.setCartTotalPrice(cartTotalPrice);cartVo.setCartProductVoList(cartProductVoList);return ResponseVo.success(cartVo);}@Overridepublic ResponseVo<CartVo> update(Integer uid, Integer productId, CartUpdateForm form) {HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();String redisKey  = String.format(CART_REDIS_KEY_TEMPLATE, uid);String value = opsForHash.get(redisKey, String.valueOf(productId));if (StringUtils.isEmpty(value)) {//没有该商品, 报错return ResponseVo.error(ResponseEnum.CART_PRODUCT_NOT_EXIST);}//已经有了,修改内容Cart cart = gson.fromJson(value, Cart.class);if (form.getQuantity() != null&& form.getQuantity() >= 0) {cart.setQuantity(form.getQuantity());}if (form.getSelected() != null) {cart.setProductSelected(form.getSelected());}opsForHash.put(redisKey, String.valueOf(productId), gson.toJson(cart));return list(uid);}@Overridepublic ResponseVo<CartVo> delete(Integer uid, Integer productId) {HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();String redisKey  = String.format(CART_REDIS_KEY_TEMPLATE, uid);String value = opsForHash.get(redisKey, String.valueOf(productId));if (StringUtils.isEmpty(value)) {//没有该商品, 报错return ResponseVo.error(ResponseEnum.CART_PRODUCT_NOT_EXIST);}opsForHash.delete(redisKey, String.valueOf(productId));return list(uid);}@Overridepublic ResponseVo<CartVo> selectAll(Integer uid) {HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();String redisKey  = String.format(CART_REDIS_KEY_TEMPLATE, uid);for (Cart cart : listForCart(uid)) {cart.setProductSelected(true);opsForHash.put(redisKey,String.valueOf(cart.getProductId()),gson.toJson(cart));}return list(uid);}@Overridepublic ResponseVo<CartVo> unSelectAll(Integer uid) {HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();String redisKey  = String.format(CART_REDIS_KEY_TEMPLATE, uid);for (Cart cart : listForCart(uid)) {cart.setProductSelected(false);opsForHash.put(redisKey,String.valueOf(cart.getProductId()),gson.toJson(cart));}return list(uid);}@Overridepublic ResponseVo<Integer> sum(Integer uid) {Integer sum = listForCart(uid).stream().map(Cart::getQuantity).reduce(0, Integer::sum);return ResponseVo.success(sum);}public List<Cart> listForCart(Integer uid) {HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();String redisKey  = String.format(CART_REDIS_KEY_TEMPLATE, uid);Map<String, String> entries = opsForHash.entries(redisKey);List<Cart> cartList = new ArrayList<>();for (Map.Entry<String, String> entry : entries.entrySet()) {cartList.add(gson.fromJson(entry.getValue(), Cart.class));}return cartList;}}

相关文章:

SpringBoot + redis处理购物车逻辑

1、pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 2、application.xml spring: characterEncodingutf-8&useSSLfalseredis:host: 127.0.…...

open cv学习 (五) 图像的阈值处理

图像的阈值处理 demo1 # 二值化处理黑白渐变图 import cv2 img cv2.imread("./img.png", 0) # 二值化处理 t1, dst cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) cv2.imshow("img", img) cv2.imshow("dst", dst) cv2.waitKey() cv2.des…...

NVIDIA vGPU License许可服务器高可用全套部署秘籍

第1章 前言 近期遇到比较多的场景使用vGPU&#xff0c;比如Citrix 3D场景、Horizon 3D场景&#xff0c;还有AI等&#xff0c;都需要使用显卡设计研发等&#xff0c;此时许可服务器尤为重要&#xff0c;许可断掉会出现掉帧等情况&#xff0c;我们此次教大家部署HA许可服务器。 …...

基于CNN卷积神经网络的口罩检测识别系统matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................ % 循环处理每张输入图像 for…...

《HeadFirst设计模式(第二版)》第九章代码——迭代器模式

情景&#xff1a; 一家早餐店和一家午餐点准备合并在一起&#xff0c;两家的点菜的菜单实现方式如下: 首先&#xff0c;他们的菜单选项都基于同一个类&#xff1a; 菜单选项类 package Chapter9_IteratorPattern.Origin;/*** Author 竹心* Date 2023/8/17**/public class Men…...

Electron入门,项目启动。

electron 简单介绍&#xff1a; 实现&#xff1a;HTML/CSS/JS桌面程序&#xff0c;搭建跨平台桌面应用。 electron 官方文档&#xff1a; [https://electronjs.org/docs] 本文是基于以下2篇文章且自行实践过的&#xff0c;可行性真实有效。 文章1&#xff1a; https://www.cnbl…...

深入理解索引B+树的基本原理

目录 1. 引言 2. 为什么要使用索引&#xff1f; 3. 索引的概述 4. 索引的优点是什么&#xff1f; 4.1 降低数据库的IO成本&#xff0c;提高数据查找效率 4.2 保证数据库每一行数据的唯一性 4.3 加速表与表之间的连接 4.4 减少查询中分组与排序的执行时间 5. 索引的缺点…...

vue3 简易用对话框实现点击头像放大查看

设置头像悬停手势 img:hover{cursor: pointer;}效果&#xff1a; 编写对话框 <el-dialog class"bigAvatar"style"border-radius: 4px;"v-model"deleteDialogVisible"title"查看头像"top"5px"><div><img src&…...

opencv 矩阵运算

1.矩阵乘&#xff08;*&#xff09; Mat mat1 Mat::ones(2,3,CV_32FC1);Mat mat2 Mat::ones(3,2,CV_32FC1);Mat mat3 mat1 * mat2; //矩阵乘 结果 2.元素乘法或者除法&#xff08;mul&#xff09; Mat m Mat::ones(2, 3, CV_32FC1);m.at<float>(0, 1) 3;m.at…...

第四章 字符串part01

344.反转字符串 public void reverseString(char[] s) {int len s.length;int left 0;int right len-1;while (left < right){char tmp s[right];s[right] s[left];s[left] tmp;left;right--;} }反转字符串II 注意String不可变&#xff0c;因此可使用char数组或者St…...

Python3内置函数大全

吐血整理 Python3内置函数大全 1.abs()函数2.all()函数3.any()函数4.ascii()函数5.bin()函数6.bool()函数7.bytes()函数8.challable()函数9.chr()函数10.classmethod()函数11.complex()函数12.complie()函数13.delattr()函数14.dict()函数15.dir()函数16.divmod()函数17.enumer…...

什么是“新型基础设施”?建设重点是什么?

一是信息基础设施。主要是指基于新一代信息技术演化生成的基础设施&#xff0c;比如&#xff0c;以5G、物联网、工业互联网、卫星互联网为代表的通信网络基础设施&#xff0c;以人工智能、云计算、区块链等为代表的新技术基础设施&#xff0c;以数据中心、智能计算中心为代表的…...

混杂接口模式---vlan

策略在两个地方可以用--1、重发布 2、bgp邻居 2、二层可以干的&#xff0c;三层也可以干 3、未知单播&#xff1a;交换机的MAC地址表的记录保留时间是5分钟&#xff0c;电脑的ARP表的记录保留时间是2小时 4、route recursive-lookup tunnel 华为默认对于bgp学习来的路由不开启标…...

Greenplum多级分区表添加分区报错ERROR: no partitions specified at depth 2

一般来说&#xff0c;我们二级分区表都会使用模版&#xff0c;如果没有使用模版特性&#xff0c;那么就会报ERROR: no partitions specified at depth 2类似的错误。因为没有模版&#xff0c;必须要显式指定分区。 当然我们在建表的时候&#xff0c;如果没有指定&#xff0c;那…...

EV PV AC SPI CPI TCPI

SPI EV / PV CPI EV / ACCPI 1.25 SPI 0.8 PV 10 000 BAC 100 000EV PV * SPI 10 000 * 0.8 8000 AC EV / CPI 8000 / 1.25 6400TCPI (BAC - EV) / (BAC -AC) (100 000 - 8 000) / (100 000 - 6 400) 92 000 / 93 600 0.98290598...

【电商领域】Axure在线购物商城小程序原型图,品牌自营垂直电商APP原型

作品概况 页面数量&#xff1a;共 60 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;网上商城、品牌自营商城、商城模块插件 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本作品为品牌自营网上商城…...

Cpp基础Ⅰ之编译、链接

1 C是如何工作的 工具&#xff1a;Visual Studio 1.1 预处理语句 在.cpp源文件中&#xff0c;所有#字符开头的语句为预处理语句 例如在下面的 Hello World 程序中 #include<iostream>int main() {std::cout <"Hello World!"<std::endl;std::cin.get…...

用户新增预测(Datawhale机器学习AI夏令营第三期)

文章目录 简介任务1&#xff1a;跑通Baseline实操并回答下面问题&#xff1a;如果将submit.csv提交到讯飞比赛页面&#xff0c;会有多少的分数&#xff1f;代码中如何对udmp进行了人工的onehot&#xff1f; 任务2.1&#xff1a;数据分析与可视化编写代码回答下面的问题&#xf…...

RGOS日常管理操作

RGOS日常管理操作 一、前言二、RGOS平台概述2.1、锐捷设备的常用登陆方式2.2、使用Console登入2.3、Telnet远程管理2.4、SSH远程管理2.5、登陆软件&#xff1a;SecureCRT 三、CLI命令行操作3.1、CLI命令行基础3.2、CLI模式3.3、CLI模式互换3.4、命令行特性3.4.1、分屏显示3.4.2…...

阿里云使用WordPress搭建个人博客

手把手教你使用阿里云服务器搭建个人博客 一、免费创建服务器实例 1.1 点击试用 点击试用会需要你创建服务器实例&#xff0c;直接选择默认的操作系统即可&#xff0c;点击下一步 1.2 修改服务器账号密码 二、创建云数据库实例 2.1 免费获取云数据库使用 2.2 实例列表页 在…...

避坑指南:.NET MAUI页面跳转最常见的5个坑点及解决方案(2023最新版)

.NET MAUI页面导航避坑实战&#xff1a;5个高频问题与工业级解决方案 刚接触.NET MAUI的开发者常会在页面跳转环节踩坑——传参莫名丢失、导航堆栈突然崩溃、模态窗口关闭失效...这些问题往往消耗大量调试时间。本文将结合GitHub高星issue和StackOverflow热帖&#xff0c;拆解5…...

告别云端推理:手把手教你用Vivado HLS在AX7350开发板上部署YOLOv3(附完整工程)

从零部署YOLOv3到AX7350开发板&#xff1a;FPGA加速实战全流程解析 在边缘计算领域&#xff0c;FPGA因其低延迟、高能效和可重构特性&#xff0c;成为深度学习模型部署的热门选择。本文将带您完成YOLOv3目标检测模型在AX7350开发板上的完整部署流程&#xff0c;从环境准备到最终…...

告别调参玄学:手把手教你用‘黎卡提方程’为自动驾驶LQR控制器选择Q和R矩阵

自动驾驶轨迹跟踪实战&#xff1a;从黎卡提方程到LQR调参的工程化思考 当你在仿真环境中第一次看到自己设计的LQR控制器让车辆完美跟踪参考轨迹时&#xff0c;那种成就感难以言喻。但更多时候&#xff0c;我们面对的是震荡的超调曲线、缓慢的收敛速度&#xff0c;以及令人抓狂的…...

Dify私有化部署实战:如何在企业内网快速搭建AI开发平台(含Docker镜像打包技巧)

Dify私有化部署实战&#xff1a;企业内网AI开发平台搭建全攻略 1. 企业内网部署Dify的核心价值与挑战 在数字化转型浪潮中&#xff0c;越来越多的企业开始将AI能力纳入核心业务系统。Dify作为开源的大语言模型应用开发平台&#xff0c;其私有化部署方案尤其适合对数据安全有严…...

煤矿电液阀系统摄像仪护套连接器 DLJ01(1000)参数

在煤矿综采工作面液压支架电液控制系统中&#xff0c;摄像仪护套连接器 DLJ01(1000)作为矿用本安型摄像仪与电源、信号传输线缆之间的专用接口&#xff0c;承担着视频信号与供电的稳定传输任务。其型号中的“1000”代表线缆长度为1000mm&#xff08;1米&#xff09;&#xff0c…...

Repomix Git日志集成:掌握commit历史分析的终极指南

Repomix Git日志集成&#xff1a;掌握commit历史分析的终极指南 【免费下载链接】repomix &#x1f4e6; Repomix (formerly Repopack) is a powerful tool that packs your entire repository into a single, AI-friendly file. Perfect for when you need to feed your codeb…...

OpCore-Simplify:零基础黑苹果配置终极指南,5分钟搞定复杂EFI

OpCore-Simplify&#xff1a;零基础黑苹果配置终极指南&#xff0c;5分钟搞定复杂EFI 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为黑苹果配置…...

5分钟搞定OpenClaw+GLM-4.7-Flash:星图平台一键部署体验

5分钟搞定OpenClawGLM-4.7-Flash&#xff1a;星图平台一键部署体验 1. 为什么选择云端部署OpenClaw 作为一个长期折腾本地AI部署的技术爱好者&#xff0c;我深知在个人电脑上配置OpenClaw的痛处。从Node.js版本冲突到模型权重下载失败&#xff0c;再到各种依赖库缺失&#xf…...

当Navicat密码遗忘时:开源解密工具如何重建数据库连接通路

当Navicat密码遗忘时&#xff1a;开源解密工具如何重建数据库连接通路 【免费下载链接】navicat_password_decrypt 忘记navicat密码时,此工具可以帮您查看密码 项目地址: https://gitcode.com/gh_mirrors/na/navicat_password_decrypt 数据库连接中断的三大痛点场景 场…...

美国是如何对GEO进行监管的?

一、GEO投毒并不是中国独有 2026年央视“315”晚会首次把“GEO投毒”这一灰色产业链推到台前。所谓“投毒”&#xff0c;说白了&#xff0c;就是有人通过批量制造虚假信息、污染训练或检索数据&#xff0c;去干扰AI的推荐和回答结果&#xff0c;最后把一些虚假、低质甚至根本不…...