苍穹外卖项目笔记(8)— 缓存商品、购物车功能

前言

代码链接:

Echo0701/take-out⁤ (github.com)

1 缓存菜品

1.1 问题说明

【注】很多时候系统性能的瓶颈就在于数据库这端

1.2 实现思路

通过 Redis 来缓存数据,减少数据库查询操作

【注】Redis 基于内存来保存数据的,访问 Redis 数据本质上是对内存的操作,而查询数据库本质上是对磁盘IO的操作

缓存逻辑分析: 

1.3 代码开发

1.3.1 缓存菜品数据

DishController.java

@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate RedisTemplate redisTemplate;/*** 根据分类id查询菜品** @param categoryId* @return*/@GetMapping("/list")@ApiOperation("根据分类id查询菜品")public Result<List<DishVO>> list(Long categoryId) {//构造 redis 中的 key,规则:dish_分类idString key = "dish_" + categoryId;//查询 redis 中是否存在菜品数据List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);if (list != null && list.size() > 0) {//如果存在,直接返回,无须查询数据库return Result.success(list);}Dish dish = new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品//如果不存在,查询数据库,将查询到的数据放入 redis 中list = dishService.listWithFlavor(dish);redisTemplate.opsForValue().set(key, list);return Result.success(list);}}

【注】如果出现异常:java.lang.reflect.InvocationTargetException,可能原因:

 ① 未进行注入,检查 @Autowired

 ② 未启动 Redis 服务器:打开 redis 的安装目录在地址栏输入cmd,输入

redis-server.exe redis.windows.conf

1.3.2 清理缓存数据

修改管理端接口 DishController 相关的方法,加入清理缓存的逻辑,需要改造的方法有:

  • 新增菜品
  • 批量删除菜品
  • 修改菜品
  • 起售停售

2 缓存套餐

2.1 Spring Cache

2.1.1 简介

Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单的加一个注释,就能实现缓存功能。它提供了一层抽象,底层可以切换不同的缓存实现,例如:

  • EHCache
  • Caffeine
  • Redis(本项目实现)

maven 坐标:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><version>2.7.3</version></dependency>

2.1.2 常用注解

2.2 实现思路

3 添加购物车

3.1 需求分析和设计

产品原型

接口设计

  • 请求方式:POST
  • 请求路径:/user/shoppingCart/add
  • 请求参数:套餐id、菜品id、口味
  • 返回结果:code、data、msg

数据库设计 

  • 购物车:暂时存放所选商品的地方
  • 选的什么商品
  • 每个商品买了几个
  • 不同用户的购物车需要区分开

【注】冗余字段(比较稳定)的设计可以帮助我们提高查询速度 ,但冗余字段不可大量设计

3.2 代码开发

ShoppingCartController.java

@RestController
@RequestMapping("/user/shoppingCart")
@Slf4j
@Api(tags = "C端购物车相关接口")
public class ShoppingCartController {@Autowiredprivate ShoppingCartService shoppingCartService;/*** 添加购物车* @param shoppingCartDTO* @return*/@PostMapping("/add")@ApiOperation("添加购物车")public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO) {log.info("添加购物车,商品信息为:{}",shoppingCartDTO);shoppingCartService.addShoppingCart(shoppingCartDTO);return Result.success();}/*** 查看购物车* @return*/@GetMapping("/list")@ApiOperation("查看购物车")public Result<List<ShoppingCart>> list() {List<ShoppingCart> list = shoppingCartService.showShoppingCart();return Result.success(list);}/*** 清空购物车* @return*/@DeleteMapping("/clean")@ApiOperation("清空购物车")public Result clean() {shoppingCartService.cleanShoppingCart();return Result.success();}/*** 减少购物车商品* @param shoppingCartDTO* @return*/@PostMapping("/sub")@ApiOperation("减少购物车商品数量")public Result sub(@RequestBody ShoppingCartDTO shoppingCartDTO) {log.info("减少购物车商品数量,商品信息为:{}", shoppingCartDTO);shoppingCartService.subShoppingCart(shoppingCartDTO);return Result.success();}
}

 

ShoppingCartServiceImpl.java

    /*** 添加购物车* @param shoppingCartDTO*/public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {// 判断当前添加的商品是否已经在购物车中存在了//select * from shopping_cart where user_id = ? and setmeal_id = xx//select * from shopping_cart where user_id = ? and dish_id = xx and dish_flavorShoppingCart shopingCart = new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO, shopingCart);Long userId = BaseContext.getCurrentId();shopingCart.setUserId(userId);List<ShoppingCart> list = shoppingCartMapper.list(shopingCart);// 若存在,只需要进行update方法更新商品数量,if(list != null && list.size() > 0) {//查到了,把这条购物车数据获取到,把 num + 1//由于user_id是唯一的,再加上上面的信息限制,所以查询的结果只可能有两种:1、查不到;2、查出来唯一的一条数据ShoppingCart cart = list.get(0);cart.setNumber(cart.getNumber() + 1); //加 1 操作以后,执行update语句:update shopping_cart set number = ? where id = ?shoppingCartMapper.updateNumberById(cart);} else{// 如果不存在才需要在购物车表里面插入一条新的数据//购物车对象仍然可以使用上面的shoppingcart,但是商品的名称、价格、图片仍然需要查询,如果是套餐到套餐表里面去查询,如果是菜品到菜品表里面去查询//判断本次添加到购物车的是菜品还是套餐,可以通过判断它们的id 是否为空来进行判断Long dishId = shoppingCartDTO.getDishId();if(dishId != null){//本次添加到购物车的是菜品Dish dish = dishMapper.getById(dishId);shopingCart.setName(dish.getName());shopingCart.setImage(dish.getImage());shopingCart.setAmount(dish.getPrice());} else {//本次添加到购物车的是套餐Long setmealId = shoppingCartDTO.getSetmealId();Setmeal setmeal = setmealMapper.getById(setmealId);shopingCart.setName(setmeal.getName());shopingCart.setImage(setmeal.getImage());shopingCart.setAmount(setmeal.getPrice());}shopingCart.setNumber(1);shopingCart.setCreateTime(LocalDateTime.now());shoppingCartMapper.insert(shopingCart);}}

ShoppingCartMapper.xml  

    <insert id="insertBatch" parameterType="list">insert into shopping_cart (name, image, user_id, dish_id, setmeal_id, dish_flavor, number, amount, create_time)values<foreach collection="shoppingCartList" item="sc" separator=",">(#{sc.name},#{sc.image},#{sc.userId},#{sc.dishId},#{sc.setmealId},#{sc.dishFlavor},#{sc.number},#{sc.amount},#{sc.createTime})</foreach></insert>

4 查看购物车

4.1 需求分析和设计

产品原型

接口设计 

4.2 代码开发

ShoppingCartServiceImpl.java

    /*** 查看购物车* @return*/public List<ShoppingCart> showShoppingCart() {//获取当前微信用户的idLong userId = BaseContext.getCurrentId();ShoppingCart shoppingCart = ShoppingCart.builder().userId(userId).build();List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);return list;}

ShoppingCartMapper.xml 

    <select id = "list" resultType="com.sky.entity.ShoppingCart">select * from shopping_cart<where>
<!--            test里面写的属性名,然后是表字段名 = #{属性名}--><if test="userId != null">and user_id = #{userId}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if><if test="dishId != null">and dish_id = #{dishId}</if><if test="dishFlavor != null">and dish_flavor = #{dishFlavor}</if></where></select>

5 清空购物车

5.1 需求分析和设计

接口设计

5.2 代码开发

ShoppingCartServiceImpl.java

    /*** 清空购物车*/public void cleanShoppingCart() {//获取当前微信用户的idLong userId = BaseContext.getCurrentId();shoppingCartMapper.deleteByUserId(userId);}

 ShoppingCartMapper.java

@Mapper
public interface ShoppingCartMapper {/*** 动态条件查询,查询条件(参数)为购物车对象* @param shoppingCart* @return*/List<ShoppingCart> list(ShoppingCart shoppingCart);/*** 根据id修改商品数量* @param shoppingCart*/@Update("update shopping_cart set number = #{number} where id = #{id}")void updateNumberById(ShoppingCart shoppingCart);/*** 插入购物车数据* @param shopingCart*/@Insert("insert into shopping_cart(name, user_id, dish_id, setmeal_id, dish_flavor, number, amount, image, create_time)" +"values (#{name}, #{userId}, #{dishId}, #{setmealId}, #{dishFlavor}, #{number}, #{amount}, #{image}, #{createTime})")void insert(ShoppingCart shopingCart);/*** 根据用户 id 清空购物车* @param userId*/@Delete("delete from shopping_cart where user_id = #{userId}")void deleteByUserId(Long userId);/*** 根据商品 id 删除购物车数据* @param id*/@Delete("delete from shopping_cart where id = #{id}")void deleteById(Long id);/*** 批量插入购物车*/void insertBatch(List<ShoppingCart> shoppingCartList);
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/210277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode208.实现Trie(前缀树)

我一开始想题目叫前缀树&#xff0c;是要用树吗&#xff1f;但是不知道用树怎么写&#xff0c;然后我就花了10多分钟&#xff0c;用了HashMap解了。map的key是word&#xff0c;value是一个放了word的所有前缀的set&#xff0c;这样search方法就非常简单了&#xff0c;只要看has…

Leetcode—2048.下一个更大的数值平衡数【中等】

2023每日刷题&#xff08;五十四&#xff09; Leetcode—2048.下一个更大的数值平衡数 实现代码 class Solution { public:int nextBeautifulNumber(int n) {for(int x n 1; ; x) {vector<int> cnt(10, 0);for(int y x; y > 0; y / 10) {cnt[y%10];}bool ok tru…

C++ Div3、Sqrt 函数高性能实现(带汇编指令集)

均采用魔法数字&#xff08;Magic Number&#xff09;实现&#xff0c;一个是经典求平方根函数所使用的魔法数字&#xff1a;0x5f375a86、0x5f3759df。 float Sqrt(float x) noexcept { /* 0x5f3759df */float xhalf 0.5f * x;int32_t i *(int32_t*)&x;i 0x5f375a86 - …

TP5上传图片压缩尺寸

图片上传&#xff0c;最简单的就是&#xff0c; 方法一&#xff1a; 修改上传限制&#xff0c;不让上传大于多少多少的图片 改一下size即可&#xff0c;默认单位是B换算成M还需要除以两次1024 方法二&#xff1a; 对上传的图片进行缩放&#xff0c;此办法网上找了不少的代码…

如何在 Azure Cosmos DB 中使用缓存

Cosmos DB 是微软在 Azure 云中发布的新 NoSQL 数据库。与关系数据库不同&#xff0c;Cosmos DB 是一种托管数据库服务&#xff0c;因此具有可扩展性&#xff0c;因此在高事务性 .NET 和 .NET Core 应用程序中很受欢迎。 但是&#xff0c;使用 Cosmos DB 时&#xff0c;您需要…

pytorch 钩子函数hook 详解及实战

文章目录 1. 介绍1.1 pytorch hook 函数种类1.2 pytorch hook 种类1.3 hook的执行顺序2. torch.Tensor.register_hook()2.1 功能2.2 语法2.3 案例3. nn.Module.register_forward_pre_hook3.1 功能3.2 语法3.3 案例4. nn

连通分量提取

图像形态学操作中的提取连通分量是一种用于分离图像中相互连接的像素区域的技术。这些像素区域通常代表着图像中的不同物体、目标或者区域。连通分量提取通常用于图像分割、对象识别、特征提取等领域。 原理&#xff1a;   连通分量提取基于图像中像素的连接性。在这个过程中…

ECharts标题字体大小自适应变化

我们在做自适应Echarts的时候,字体大小在配置项里是如下配置的, title 标题组件,包含主标题和副标题。 以下是常用的对标题的设置: title:{//设置图表的标题text:"主标题",link:"baidu.com", //设置标题超链接target:"self",

HCIP —— BGP 基础 (下)

BGP 的状态机 --- 建立对等体之间的TCP会话&#xff1a;指定建立对等体的对象 六种状态机 Idle状态 Idle 等待状态&#xff08;相当于OSPF的down状态&#xff09;--- 采用TCP单播建邻 Idle 状态下&#xff0c;启动BGP协议后必须指定建立对等体的目标之后&#xff0c;才能进入…

yaml工作常用语法总结

文章目录 yaml中的| 符号 和 > 符号yaml中的 - 符号工作中常遇到的问题- 命令行中有冒号加空格&#xff0c;导致yaml解析报错 yaml中的| 符号 和 > 符号 在 YAML 中&#xff0c;| 符号表示标量块&#xff08;Scalar Block&#xff09;的开始。它用于表示长文本块或保持多…

代码随想录算法训练营第四十六天| 139 单词拆分

目录 139 单词拆分 139 单词拆分 class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {vector<bool>dp(s.size() 1);//长度为i的字符串时能否成功拆分unordered_set<string>set(wordDict.begin(),wordDict.end());dp[0] t…

数据结构 | 查漏补缺之哈希表、最短路径、二叉树与森林的转换

哈希表是什么&#xff1f; 或者说 设图采用邻接表的存储结构&#xff0c;写对图的删除顶点和删除边的算法步骤 删除边 删除点 最短路径问题 参考博文 迪杰斯特拉(Dijkstra)算法_dijkstra算法-CSDN博客 Dijkstra(迪杰斯特拉&#xff09;算法 定义一个点为源点&#xff0c;算源…

5G+AI开花结果,助力智慧安检落地

“请带包的乘客过机安检&#xff01;”&#xff0c;深圳地铁、腾讯共同打造的5GAI智慧安检辅助系统亮相福田枢纽站&#xff0c;进一步解放了人力&#xff0c;提高安检效率&#xff0c;为交通安全保驾护航&#xff0c;让智慧出行成为现实。 传统的安检设备均为人工肉眼辨识&…

java面试题汇总-目录

坚持记录和总结一些面试过程中遇到的面试题&#xff0c;以及总结出自己的回答技巧。不用死记硬背也能完整的回答出来。会持续更新&#xff0c;欢迎提出问题和疑问&#xff0c;大家一起总结经验。 1.Hashmap、Hashtable、ConcurrentHashMap原理 2.谈谈sql优化-mysql 3.ArrayList…

2023年9月13日 Go生态洞察:WASI支持在Go中的实现

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

21、命令执行

文章目录 一、命令执行概述1.1 基本定义1.2 原理1.3 两个条件1.4 命令执行漏洞产生的原因1.5 管道符号和通用命令符 二、远程命令执行2.1 远程命令执行相关函数2.2 远程命令执行漏洞的利用 三、系统命令执行3.1 相关函数3.2 系统命令执行漏洞利用 四、命令执行漏洞防御 一、命令…

Vue笔记(三)深入组件

组件注册 组件注册有两种方式&#xff1a; 全局注册 可以使用Vue应用实例的.component()方法&#xff0c;让组件在当前Vue应用中全局可用&#xff0c;.component()方法可以被链式调用。全局注册的组件可以在此应用的任意组件的模版中使用。import { createApp } from vue imp…

阿里云生态离线数仓

1. 大数据开发治理平台 DataWorks 功能齐全&#xff1a;10多年大数据建设沉淀完整的平台&#xff0c;覆盖数据开发治理的全生命周期 简单易用&#xff1a;全图形化界面&#xff0c;SQL为主的数据开发方式 安全稳定&#xff1a;双11日千万级任务稳定调度&#x…

一:C语言常见概念

一&#xff1a;C语言常见概念 1.认识C语言&#xff1a; ​ C语言是人和计算机交流的语言 ​ C语言是一门面向过程的语言&#xff0c;而C&#xff0c;Java&#xff0c;Python等是一门面向对象的语言 ​ 软件开发&#xff08;项目&#xff09;&#xff1a;面向过程面向对象 …

maven下载安装与配置

文章目录 1. Maven下载2. 配置settings.xml2.1 指定Maven的本地仓库2.2 配置阿里云提供的镜像仓库2.3 配置 Maven 工程的基础 JDK 版本 3. 配置环境变量3.1 检查 JAVA_HOME 配置是否正确3.2 配置 MAVEN_HOME3.3 配置PATH3.4 验证 1. Maven下载 【Maven官网地址】 【Maven下载…