苍穹外卖day07——缓存菜品套餐+购物车功能实现

缓存菜品——需求设计与分析

问题说明

用户访问量过大带来的一个直接效果就是响应速度慢,使用体验下降。

 实现思路

使用redis缓存菜品数据,减少数据库查询操作。

 页面展示上基本就是同一个分类在同一页,所以key-value结构可以使用不同的分类来做key。

缓存菜品——代码开发

在小程序每一次点击不同的分类,后端哪里都会刷刷刷的连接数据库查询返回,对后端压力肥肠的大,因此使用Redis的作用在这里就能体现了。

修改用户端的DishController代码

@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);}
}

相对应的在redis里面会有缓存数据

修改管理端的DIshController代码 

要保证数据一致性,数据库数据发生改变时要及时修改redis,不然小程序端的数据和数据库数据会不一致。

/*** 菜品管理*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags="菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate RedisTemplate redisTemplate;/*** 新增菜品* @param dishDTO* @return*/@PostMapping@ApiOperation("新增菜品")public Result save(@RequestBody DishDTO dishDTO){log.info("新增菜品:{}",dishDTO);dishService.saveWithFlavor(dishDTO);//清理缓存数据String key="dish_"+dishDTO.getCategoryId();cleanCache(key);return Result.success();}/*** 菜品分页查询* @param dishPageQueryDTO* @return*/@GetMapping("/page")@ApiOperation("菜品分页查询")public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){log.info("菜品分页查询:{}",dishPageQueryDTO);PageResult pageResult= dishService.pageQuery(dishPageQueryDTO);return Result.success(pageResult);}/*** 菜品批量删除* 通过@RequestParam注解将字符串转换为数组* @param ids* @return*/@DeleteMapping@ApiOperation("菜品批量删除")public Result delete(@RequestParam List<Long> ids){log.info("菜品批量删除:{}",ids);dishService.deleteBatch(ids);//将所有的菜品缓存数据清理掉,所有以dish_开头的keycleanCache("dish_*");return Result.success();}/*** 根据id查询菜品* @param id* @return*/@GetMapping("/{id}")@ApiOperation("根据id查询菜品")public Result<DishVO> getById(@PathVariable Long id){log.info("根据id查询菜品:{}",id);DishVO dishVO=dishService.getByIdWithFlavor(id);return Result.success(dishVO);}/*** 根据id修改菜品基本信息和对应口味信息* @param dishDTO* @return*/@PutMapping@ApiOperation("修改菜品")public Result update(@RequestBody DishDTO dishDTO){log.info("修改菜品:{}",dishDTO);dishService.updateWithFlavor(dishDTO);//将所有的菜品缓存数据清理掉,所有以dish_开头的keycleanCache("dish_*");return Result.success();}/*** 根据分类id查询菜品* @param categoryId* @return*/@GetMapping("list")@ApiOperation("根据分类id查询菜品")public Result<List<Dish>> list(Long categoryId){List<Dish> list=dishService.list(categoryId);return Result.success(list);}/*** 菜品起售停售* @param status* @param id* @return*/@PostMapping("/status/{status}")@ApiOperation("菜品起售停售")public Result<String> startOrStop(@PathVariable Integer status, Long id){dishService.startOrStop(status,id);//将所有的菜品缓存数据清理掉,所有以dish_开头的keycleanCache("dish_*");return Result.success();}/*** 清理缓存数据* @param pattern*/private void cleanCache(String pattern){Set keys = redisTemplate.keys(pattern);redisTemplate.delete(keys);}
}

缓存菜品——功能测试

不做了,好累啊。

缓存套餐——Spring Cache

在以下这个文章里面。Spring Cache_北岭山脚鼠鼠的博客-CSDN博客

实现思路+代码开发

 在启动类上加入注解

@EnableCaching //开启缓存注解的功能

 user端

    /*** 条件查询** @param categoryId* @return*/@GetMapping("/list")@ApiOperation("根据分类id查询套餐")@Cacheable(cacheNames = "sermealCache",key="#categoryId")public Result<List<Setmeal>> list(Long categoryId) {Setmeal setmeal = new Setmeal();setmeal.setCategoryId(categoryId);setmeal.setStatus(StatusConstant.ENABLE);List<Setmeal> list = setmealService.list(setmeal);return Result.success(list);}

admin端

/*** 套餐管理*/
@RestController
@RequestMapping("/admin/setmeal")
@Api(tags="套餐相关接口")
@Slf4j
public class SetmealController {@Autowiredprivate SetmealService setmealService;/*** 新增套餐* @param setmealDTO* @return*/@PostMapping@ApiOperation("新增套餐")@CacheEvict(cacheNames = "setmealCachce",key="#setmealDTO.categoryId")public Result save(@RequestBody SetmealDTO setmealDTO){setmealService.saveWithDish(setmealDTO);return Result.success();}/*** 分页查询* @param setmealPageQueryDTO* @return*/@GetMapping("/page")@ApiOperation("分页查询")public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO){PageResult pageResult=setmealService.pageQuery(setmealPageQueryDTO);return Result.success(pageResult);}/*** 批量删除套餐* @param ids* @return*/@DeleteMapping@ApiOperation("批量删除套餐")@CacheEvict(cacheNames = "setmealCache",allEntries = true)public Result delete(@RequestParam List<Long> ids){setmealService.deleteBatch(ids);return Result.success();}/*** 根据id查询套餐,用于修改页面回显数据** @param id* @return*/@GetMapping("/{id}")@ApiOperation("根据id查询套餐")public Result<SetmealVO> getById(@PathVariable Long id) {SetmealVO setmealVO = setmealService.getByIdWithDish(id);return Result.success(setmealVO);}/*** 修改套餐** @param setmealDTO* @return*/@PutMapping@ApiOperation("修改套餐")@CacheEvict(cacheNames = "setmealCache",allEntries = true)public Result update(@RequestBody SetmealDTO setmealDTO) {setmealService.update(setmealDTO);return Result.success();}/*** 套餐起售停售* @param status* @param id* @return*/@PostMapping("/status/{status}")@ApiOperation("套餐起售停售")@CacheEvict(cacheNames = "setmealCache",allEntries = true)public Result startOrStop(@PathVariable Integer status, Long id) {setmealService.startOrStop(status, id);return Result.success();}
}

缓存套餐——功能测试

测试无误

虽然但是,明明小程序没有显示东西,但是数据还是进了缓存。

 添加购物车——需求分析与设计

产品原型

购物车就是暂时存放所选商品的地方。

没有口味就是直接加入购物车,有口味要先选择口味。

接口设计

 

数据库设计

 冗余字段的存在减少了查询次数。

 添加购物车——代码开发(1)

用到的DTO

 Controller层中

@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();}
}

Service层中

@Service
@Slf4j
public class ShoppingCartServiceImpl implements ShoppingCartService {@Autowiredprivate ShoppingCartMapper shoppingCartMapper;@Autowiredprivate DishMapper dishMapper;@Autowiredprivate SetmealMapper setmealMapper;/*** 添加购物车* @param shoppingCartDTO*/@Overridepublic void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {//判断当前加入购物车的商品是否存在ShoppingCart shoppingCart = new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO,shoppingCart); //属性拷贝Long userId = BaseContext.getCurrentId();  //拦截器获取到的用户idshoppingCart.setUserId(userId);List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);//如果已经存在了,只需要将数量加一if(list!=null&&list.size()>0){//这里list要么没有数据,要么只有一条数据ShoppingCart cart = list.get(0);cart.setNumber(cart.getNumber()+1); //update shopping_cart set number=?where id=?shoppingCartMapper.updateNumberById(cart);}else {//如果不存在,需要插入一条购物车数据/*** 判断这次添加到购物车的是菜品还是套餐*/Long dishId = shoppingCartDTO.getDishId();if(dishId!=null){//本次添加是菜品Dish dish = dishMapper.getById(dishId);shoppingCart.setName(dish.getName());shoppingCart.setImage(dish.getImage());shoppingCart.setAmount(dish.getPrice());}else{//本次添加的是套餐Long setmealId = shoppingCartDTO.getSetmealId();Setmeal setmeal = setmealMapper.getById(setmealId);shoppingCart.setName(setmeal.getName());shoppingCart.setImage(setmeal.getImage());shoppingCart.setAmount(setmeal.getPrice());}shoppingCart.setNumber(1);shoppingCart.setCreateTime(LocalDateTime.now());//统一插入数据shoppingCartMapper.insert(shoppingCart);}}
}

Mapper层中

@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 shoppingCart*/@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 shoppingCart);
}

对应的映射文件

<mapper namespace="com.sky.mapper.ShoppingCartMapper"><select id="list" resultType="com.sky.entity.ShoppingCart">select * from shopping_cart<where><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>
</mapper>

 添加购物车——功能测试

前端点击添加成功有新数据

查看购物车——需求分析和设计+代码开发+功能测试

产品原型

 接口设计

Controller中

    /*** 查看购物车* @return*/@GetMapping("/list")@ApiOperation("查看购物车")public Result<List<ShoppingCart>> list(){List<ShoppingCart>list=shoppingCartService.showShoppingCart();return Result.success(list);}

Service中

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

mapper层已经有了

功能测试

清空购物车——需求分析和设计+代码开发+功能测试

产品原型

店家清空直接删除所有数据

 接口设计

Controller中

    /*** 清空购物车* @return*/@DeleteMapping("/clean")@ApiOperation("清空购物车")public Result clean(){shoppingCartService.cleanShoppingCart();return Result.success();}

Service中

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

mapper中

    /*** 根据用户id删除购物车数据* @param userId*/@Delete("delete from shopping_cart where user_id = #{userId}")void deleteById(Long userId);

功能测试不写了,反正没人看

删除购物车——需求分析与设计

产品原型

点击减号可以减少一个或者是直接删除

 接口设计

 Controller层中

    /*** 删除购物车商品* @param shoppingCartDTO* @return*/@PostMapping("/sub")@ApiOperation("/删除购物车商品")public Result sub(ShoppingCartDTO shoppingCartDTO){log.info("删除商品信息:{}",shoppingCartDTO);shoppingCartService.subShoppingCart(shoppingCartDTO);return Result.success();}

Service层中

    /*** 删除购物车数据* @param shoppingCartDTO*/@Overridepublic void subShoppingCart(ShoppingCartDTO shoppingCartDTO) {ShoppingCart shoppingCart=new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);//获取用户id,查询当前登录用户的idshoppingCart.setId(BaseContext.getCurrentId());List<ShoppingCart> list=shoppingCartMapper.list(shoppingCart);if(list!=null&&list.size()>0){shoppingCart=list.get(0);Integer number = shoppingCart.getNumber();if(number==1){//当前商品在购物车中的份数为1,直接删除当前记录shoppingCartMapper.deleteById2(shoppingCart.getId());}else{//当前商品在购物车中的份数不为1,修改份数即可shoppingCart.setNumber(shoppingCart.getNumber() - 1);shoppingCartMapper.updateNumberById(shoppingCart);}}}

Mapper层中

这个删除是根据id删除,上面的是根据userId删除,两者不同的。

    /*** 根据id删除购物车数据* @param id*/@Delete("delete from shopping_cart where id = #{id}")void deleteById2(Long id);

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

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

相关文章

【Git】版本回退与撤销修改案例

目录 一、版本回退 二、撤销修改案例 案例1&#xff1a;仅在工作区进行了修改还未进行add操作 案例2&#xff1a;仅进行了add 操作还未进行commit操作 案例3&#xff1a;进行了add与commit操作无其他操作 三、版本库中删除文件 一、版本回退 在进行版本回退之前我们需要…

Excel的使用

1.EXCEL诞生的意义 1.1 找到想要的数据 1.2 提升输入速度 2.数据分析与可视化操作 目的是提升数据的价值和意义 3.EXCEL使用的内在意义和外在形式 4.EXCEL的价值 4.1 解读及挖掘数据价值 4.2 协作板块 4.3 展示专业度 4.4 共享文档内容 5.人的需求》》软件功能

【UE4】局域网多人联机 Demo

效果 亲测可以打包后在两个电脑上联机运行&#xff08;前提是在同一个局域网内&#xff0c;互相能ping通&#xff09; 步骤 1. 首先新建一个第三人称角色模板工程 2. 在多玩家选项中&#xff0c;设置玩家数量为2 选择在新建编辑器窗口中运行 3. 新建一个父类为Character的蓝…

wangeditor 表格问题总结及适配方案

一、导出编辑器内容&#xff0c;表格无边框样式 1、通过 let article this.editor.getHtml(); // editor.getHtml() 获取 HTML 内容&#xff1b; 2、处理文本字符串&#xff1a;&#xff08;手动为 table 加上 css样式&#xff09;&#xff1b; article article.replace…

虎年现货黄金投资布局图

参与现货黄金交易的主要目的&#xff0c;是为了根据行情走势的变动&#xff0c;把握一些较佳的获利机会&#xff0c;在这样的一个过程中&#xff0c;如果投资者能够提前把布局的图表画好&#xff0c;那么就可能获得事半功倍的效果&#xff0c;而本文将为大家简单的介绍&#xf…

【主成分分析(PCA)- 鸢尾花】

主成分分析&#xff08;PCA&#xff09; 摘要 在现代数据科学中&#xff0c;维度灾难常常是数据处理与分析的一大难题。主成分分析&#xff08;PCA&#xff09;是一种广泛使用的数据降维技术&#xff0c;它通过将原始数据转换为新的低维空间&#xff0c;保留最重要的信息&…

15.Netty源码之EventLoop

highlight: arduino-light Netty配置主从Reactor模式 通过将NioServerSocketChannel绑定到了bossGroup。 将NioServerSocketChannel接收到请求创建的SocketChannel放入workerGroup。 将2个不同的SocketChannel绑定到2个不同的Group完成了主从 Reactor 模式。 分配NIOEventLoop的…

论文精读之BERT

目录 1.摘要&#xff08;Abstract&#xff09; 2.引言&#xff08;Introduction&#xff09;&#xff1a; 3.结论&#xff08;Conlusion&#xff09;&#xff1a; 4.BERT模型算法: 5.总结 1.摘要&#xff08;Abstract&#xff09; 与别的文章的区别是什么:BERT是用来设计去…

springboot创建并配置环境(三) - 配置扩展属性(上集)

文章目录 一、介绍二、配置文件application.yml 一、介绍 在上一篇文章&#xff1a;springboot创建并配置环境(二) - 配置基础环境中&#xff0c;我们介绍了springboot如何配置基础环境变量。本篇文章讨论如何处理配置文件。即来自不同位置的配置属性&#xff0c;如&#xff1…

【Chat GPT】用 ChatGPT 运行 Python

前言 ChatGPT 是一个基于 GPT-2 模型的人工智能聊天机器人&#xff0c;它可以进行智能对话&#xff0c;同时还支持 Python 编程语言的运行&#xff0c;可以通过 API 接口进行调用。本文将介绍如何使用 ChatGPT 运行 Python 代码&#xff0c;并提供一个实际代码案例。 ChatGPT …

简单理解大模型参数高效微调中的LoRA(Low-Rank Adaptation)

[论文地址] [代码] [ICLR 22] 阅前须知&#xff1a;本博文可能有描述不准确/过度简化/出错的地方&#xff0c;仅供参考。 网络结构 其中&#xff0c;原有模型的参数是直接冻结的&#xff0c;可训练参数只有额外引入的LoRA参数(由nn.Parameter实现)。 模型微调的本质 记网络原…

LabVIEW实现三相异步电机磁通模型

LabVIEW实现三相异步电机磁通模型 三相异步电动机由于经济和出色的机电坚固性而广泛用于工业化应用。这台机器的设计和驱动非常简单&#xff0c;但在控制扭矩和速度方面&#xff0c;它隐藏了相当大的功能复杂性。通过数学建模&#xff0c;可以理解机器动力学。 基于微分方程的…

【嵌入式学习笔记】嵌入式基础9——STM32启动过程

1.MAP文件浅析 1.1.MDK编译后生成的中间过程文件 1.2.Map文件构成&#xff1a; 程序段交叉引用关系&#xff08;Section Cross References&#xff09;&#xff1a;描述各文件之间函数调用关系删除映像未使用的程序段&#xff08;Removing Unused input sections from the im…

【图像处理】使用 OpenCV 将您的照片变成卡通

图像到卡通 一、说明 在当今世界&#xff0c;我们被图像和视频所包围。从社交媒体到广告&#xff0c;图像已成为一种强大的交流媒介。但是你有没有想过&#xff0c;如果你能把你的照片变成卡通会发生什么&#xff1f;想象一下&#xff0c;为您最喜欢的照片创建动画版本&#xf…

Pytorch深度学习-----神经网络的基本骨架-nn.Module的使用

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用&#xff08;ToTensor&#xff0c;Normalize&#xff0c;Resize &#xff0c;Co…

python爬虫基础入门——利用requests和BeautifulSoup

(本文是自己学习爬虫的一点笔记和感悟) 经过python的初步学习,对字符串、列表、字典、元祖、条件语句、循环语句……等概念应该已经有了整体印象,终于可以着手做一些小练习来巩固知识点,写爬虫练习再适合不过。 1. 网页基础 爬虫的本质就是从网页中获取所需的信息,对网…

类加载机制与类加载器

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ Java 源码是如何形成类文件的&#xff0c;类文件又是如何加载到虚拟机的&#xff0c;类加载有哪些机制和原则呢&#xff1f;本文将为大家一一介绍。 1 Java 源码形成类文件…

基于拉格朗日-遗传算法的最优分布式能源DG选址与定容(Matlab代码实现)

目录 1 概述 2 数学模型 2.1 问题表述 2.2 DG的最佳位置和容量&#xff08;解析法&#xff09; 2.3 使用 GA 进行最佳功率因数确定和 DG 分配 3 仿真结果与讨论 3.1 33 节点测试配电系统的仿真 3.2 69 节点测试配电系统仿真 4 结论 1 概述 为了使系统网损达到最低值&a…

AI Chat 设计模式:10. 组合模式

本文是该系列的第八篇&#xff0c;采用问答式的方式展开&#xff0c;问题由我提出&#xff0c;答案由 Chat AI 作出&#xff0c;灰色背景的文字则主要是我的一些思考和补充。 问题列表 Q.1 给我介绍一下组合模式A.1Q.2 好的&#xff0c;给我举一个组合模式的例子&#xff0c;使…

idea导入maven项目问题

问题产生原因&#xff1a; ①idea加载maven项目&#xff0c;如果网络不通畅&#xff0c;会在maven仓库中产生一个文件&#xff0c;如下图所示: ②当网络通畅时&#xff0c;在下载就会因为此文件导致无法下载正确的maven依赖 解决方案&#xff1a; ①打开maven仓库的根目录 ②…