【苍穹外卖】Day 7 缓存、购物车相关接口

news/2024/9/19 11:21:08/ 标签: 数据库

1 缓存

存在问题:

        用户端小程序展示的菜品数据都是通过査询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大

=>解决:

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

缓存逻辑分析:

  • 每个分类下的菜品保存一份缓存数据
  • 数据库中菜品数据有变更时清理缓存数据

浏览菜品页面使用的路径:

GET  /user/dish/list?categoryId=1

在 redis 这样保存

package com.sky.controller.user;import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@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) {// 1.查询 redis 中是否有菜品数据//构造 keyString key = "dish_" + categoryId.toString();List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);if (list != null && list.size() > 0) {// 2.如果有,直接返回return Result.success(list);}// 3.如果没有,先去数据库查询,然后数据缓存在 redis,返回Dish dish = new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品list = dishService.listWithFlavor(dish);//缓存redisredisTemplate.opsForValue().set(key, list);return Result.success(list);}}

清理缓存

        当修改完菜品信息时,修改了sql数据库,但再去浏览菜品,访问的是 redis,需要 清理缓存
 

然后在增删改操作return前,加上

cleanCache("dish_*");

2 Spring Cache

        Spring Cache 提供了一层抽象,底层可以切换不同的缓存实观,例如:

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

 

/*** 新增菜品,不光加入 菜品表 dish 还有 口味表 dish flavor** @param dishDTO* @return*/@PostMapping@ApiOperation("新增菜品")@CacheEvict(cacheNames = "dishCache",key = "#dishDTO.categoryId")public Result add(@RequestBody DishDTO dishDTO) {log.info("新增菜品");dishService.add(dishDTO);return Result.success();}

如果不好获得categoryId,就全删除

@CacheEvict(cacheNames = "dishCache",allEntries = true)
/*** 根据菜品 id 删除菜品** @param ids* @return*/@DeleteMapping@ApiOperation("根据菜品 id 删除菜品")@CacheEvict(cacheNames = "dishCache",allEntries = true)public Result deleteById(@RequestParam List<Long> ids) {dishService.delete(ids);return Result.success();}

为什么不是 key = "#{dishDTO.categoryId}":

  • # 用于在Spring缓存注解中的SpEL表达式,表示引用方法参数
  • #{} 用于解析Spring上下文中的Bean或者系统属性

3 缓存套餐

【增删改】要 【删除缓存】---> @CacheEvict

【查】要【访问缓存】---> @Cacheable

 

对于用户端:

        只能查询,不能增删改,所以只加 @Cacheable

对于管理端:

/*** 新增套餐** @param setmealDTO* @return*/@PostMapping@ApiOperation("新增套餐")@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")public Result add(@RequestBody SetmealDTO setmealDTO) {setmealService.add(setmealDTO);return Result.success();}

4 添加购物车

4.1 设计

 

 设计冗余字段:用空间换时间

4.2 实现

controller

service

package com.sky.service.impl;import com.sky.context.BaseContext;
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.ShoppingCart;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.ShoppingCartService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;@Service
public class ShoppingCartServiceImpl implements ShoppingCartService {@Autowiredprivate ShoppingCartMapper shoppingCartMapper;@Autowiredprivate DishMapper dishMapper;@Autowiredprivate SetmealMapper setmealMapper;/*** 添加购物车** @param shoppingCartDTO*/public void add(ShoppingCartDTO shoppingCartDTO) {//判断当前商品是否购物车中已存在ShoppingCart shoppingCart = new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO, shoppingCart);Long userId = BaseContext.getCurrentId();shoppingCart.setUserId(userId);List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);if (list != null && list.size() > 0) {//如果存在,数量加一ShoppingCart cart = list.get(0); // 直接取出唯一的一条数据cart.setNumber(cart.getNumber() + 1);shoppingCartMapper.updateNumberById(cart);} else {//如果不存在,插入数据//首先构造一个 ShoppingCart 对象//再补充数据://name image amount create_timeLong dishId = shoppingCart.getDishId();Long setmealId = shoppingCart.getSetmealId();if (dishId != null) {// 查询菜品表获取 name image amountDish dish = dishMapper.getById(dishId);shoppingCart.setName(dish.getName());shoppingCart.setImage(dish.getImage());shoppingCart.setAmount(dish.getPrice());shoppingCart.setNumber(1); // 注意要设置数量为 1} else {// 查询套餐表获取 name image amountSetmeal setmeal = setmealMapper.getById(setmealId);shoppingCart.setName(setmeal.getName());shoppingCart.setImage(setmeal.getImage());shoppingCart.setAmount(setmeal.getPrice());shoppingCart.setNumber(1); // 注意要设置数量为 1}shoppingCart.setCreateTime(LocalDateTime.now());}shoppingCartMapper.insert(shoppingCart);}
}

mapper

package com.sky.mapper;import com.sky.entity.ShoppingCart;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;import java.util.List;@Mapper
public interface ShoppingCartMapper {/*** 条件查询购物车** @param shoppingCartDTO* @return*/List<ShoppingCart> list(ShoppingCart shoppingCartDTO);/*** 根据id更新菜品数量number(加一)** @param cart*/@Update("update sky_take_out.shopping_cart set number = #{number} where id = #{id}")void updateNumberById(ShoppingCart cart);/*** 加入购物车* @param shoppingCart*/@Insert("insert into sky_take_out.shopping_cart" +"(name, image, user_id, dish_id, setmeal_id, dish_flavor, amount, create_time)" +"values" +"(#{name},#{image},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{amount},#{createTime})")void insert(ShoppingCart shoppingCart);
}

xml

<select id="list" resultType="com.sky.entity.ShoppingCart">select *from sky_take_out.shopping_cart<where><if test="userId != null">and user_id = #{userId}</if><if test="dishId != null">and dish_id = #{dishId}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if><if test="dishFlavor != null">and dish_flavor = #{dishFlavor}</if></where>
</select>

4.3 测试

5 查看购物车 与 清空购物车

查看

Path:/user/shoppingCart/list

Method:GET

清空

Path:/user/shoppingCart/clean

Method:DELETE

controller

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

 service

    /*** 查看购物车*/@Overridepublic List<ShoppingCart> list() {List<ShoppingCart> list = shoppingCartMapper.listAll();return list;}/*** 清空购物车*/@Overridepublic void clean() {shoppingCartMapper.clean();}

mapper

/*** 查看购物车,返回所有数据** @return*/@Select("select * from sky_take_out.shopping_cart")List<ShoppingCart> listAll();/*** 清空购物车*/@Delete("delete from sky_take_out.shopping_cart")void clean();

测试


http://www.ppmy.cn/news/1522966.html

相关文章

如何使用“Python 实现斐波那契数列的方法“?

def fibonacci(n):if n < 1:return nelse:return fibonacci(n - 1) fibonacci(n - 2)num_terms 10 for i in range(num_terms):print(fibonacci(i), end" ") 在这个程序中&#xff0c;定义了一个函数fibonacci&#xff0c;它接受一个参数n。如果n小于等于 1&am…

【Python机器学习】词向量推理——词向量

目录 面向向量的推理 使用词向量的更多原因 如何计算Word2vec表示 skip-gram方法 什么是softmax 神经网络如何学习向量表示 用线性代数检索词向量 连续词袋方法 skip-gram和CBOW&#xff1a;什么时候用哪种方法 word2vec计算技巧 高频2-gram 高频词条降采样 负采样…

Java和.equals()的区别

1.""比较基本数据类型时比较的是表面值内容&#xff0c;而比较两个对象时比较的是两个对象的内存地址值。 2. 在基本数据类型&#xff1a;值内容, 引用类型时&#xff1a;地址 equals 重写&#xff1a;值内容 &#xff0c; equals不重写&#xf…

网络安全 day4 --- APP架构小程序H5+Vue语言Web封装原生开发Flutter

APP架构 1、原生开发 安卓一般使用java语言开发&#xff0c;当然现在也有kotlin语言进行开发。如何开发就涉及到具体编程了&#xff0c;这里就不详说了。简单描述就是使用安卓提供的一系列控件来实现页面&#xff0c;复杂点的页面可以通过自定义控件来实现。 2、使用H5语言开发…

Mybatis-PageHelper Reentrantlock锁使用问

Mybatis-PageHelper应该是目前使用比较广泛的一个Mybatis分页插件。我在几个项目里都引入了该插件。今天偶然阅读其源码&#xff0c;却发现了一个不小的问题。 注&#xff1a;我阅读的是最新的4.1.3的源码。 该分页插件的核心是PageHelper类&#xff0c;该类实现了Mybatis提供的…

在C++中,如何避免出现Bug?

C中的主要问题之一是存在大量行为未定义或对程序员来说意外的构造。我们在使用静态分析器检查各种项目时经常会遇到这些问题。但正如我们所知&#xff0c;最佳做法是在编译阶段尽早检测错误。让我们来看看现代C中的一些技术&#xff0c;这些技术不仅帮助编写简单明了的代码&…

【HarmonyOS】安装包报错,code:9568282 error: install releaseType target not same.

【HarmonyOS】安装包报错&#xff0c;code:9568282 error: install releaseType target not same. 报错信息 Install Failed: error: failed to install bundle. code:9568282 error: install releaseType target not same. You can also uninstall and reinstall the module…

鸿蒙(API 12 Beta6版)【ArkGraphics 3D资源创建以及使用】方舟3D图形

3D场景中资源类型主要包含以下几种&#xff1a; 材质&#xff08;Material&#xff09;&#xff1a; 材质是对场景中物体的光学物理性质的数学建模。在渲染计算的过程中&#xff0c;利用这些物理性质计算与光的相互作用&#xff0c;得到最终渲染的颜色。ArkGraphics 3D提供的材…

Arduino IDE安装操作指南

Arduino是一个基于开源硬件和软件的平台&#xff0c;旨在使人们更容易开发电子项目。Arduino IDE&#xff08;集成开发环境&#xff09;是用于编写代码、编译和上传到Arduino开发板的工具。无论是电子爱好者、新手还是专业开发者&#xff0c;Arduino IDE都是一个不可或缺的工具…

人工智能在C/C++中的应用

随着技术的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已经成为我们日常生活中不可或缺的一部分。从智能手机的语音助手到自动驾驶汽车&#xff0c;AI的应用无处不在。在众多编程语言中&#xff0c;C和C因其高性能和灵活性&#xff0c;成为实现复杂AI算法的理想选…

HivisionIDPhotos-证件照-免费开源的AI证件照制作工具

HivisionIDPhoto 旨在开发一种实用的证件照智能制作算法。 它利用一套完善的模型工作流程&#xff0c;实现对多种用户拍照场景的识别、抠图与证件照生成。 HivisionIDPhoto 可以做到&#xff1a; 轻量级抠图&#xff08;仅需 CPU 即可快速推理&#xff09;根据不同尺寸规格生…

《Nginx核心技术》第16章:实现Nginx的高可用负载均衡

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

2024 年高教社杯全国大学生数学建模竞赛题目-C 题 农作物的种植策略

根据乡村的实际情况&#xff0c;充分利用有限的耕地资源&#xff0c;因地制宜&#xff0c;发展有机种植产业&#xff0c;对乡村经济 的可持续发展具有重要的现实意义。选择适宜的农作物&#xff0c;优化种植策略&#xff0c;有利于方便田间管理&#xff0c;提 高生产效益&#…

HTTPS访问是什么?

HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是一种安全的网络传输协议&#xff0c;它基于HTTP&#xff08;Hypertext Transfer Protocol&#xff0c;超文本传输协议&#xff09;进行工作&#xff0c;但增加了安全性的要求。HTTPS通过在客户端&#xff08…

014.PL-SQL编程

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

lvs dr模式集群搭建

lvs-dr模式 集群搭建 编辑zyj86主机网卡配置文件 cd /etc/sysconfig/network-scripts/ cp ifcfg-ens160 ifcfg-ens160:1 vim ifcfg-ens160:1TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic DEFROUTEyes IPV4_FAILURE_FATALno IPV6INITyes IPV6_AUTOCONFyes IP…

经验笔记:持续集成/持续部署(CI/CD)流程

持续集成/持续部署&#xff08;CI/CD&#xff09;流程经验笔记 随着软件开发的快速发展&#xff0c;持续集成&#xff08;Continuous Integration, CI&#xff09;和持续部署&#xff08;Continuous Deployment, CD&#xff09;已经成为现代软件工程不可或缺的部分。CI/CD不仅…

Transformer、BERT、GPT、T5、LLM(大语言模型),以及它们在实际行业中的运用

作为AI智能大模型的专家训练师&#xff0c;我将从主流模型框架的角度来分析其核心技术特点及其在不同实际行业中的应用。我们重点讨论以下几个主流模型框架&#xff1a;Transformer、BERT、GPT、T5、LLM&#xff08;大语言模型&#xff09;&#xff0c;以及它们在实际行业中的运…

【unity小技巧】使用Unity的Animation Layer和Avatar Mask把多个不同动画组合使用,实现人物不同部位播放不同的动画

文章目录 前言如何使用Unity的Animation Layer和Avatar Mask把多个动画组合使用游戏角色的疲劳感是如何制作的&#xff1f;利用Animation Layers中的additive模式把多个动画混合在一起如何制作角色的受伤状态&#xff1f;Unity动画层级&#xff08;Animation Layer&#xff09;…

ChatGPT 3.5/4.0使用手册:解锁人工智能的无限潜能

1. 引言 在人工智能的浪潮中&#xff0c;ChatGPT以其卓越的语言理解和生成能力&#xff0c;成为了一个革命性的工具。它不仅仅是一个聊天机器人&#xff0c;更是一个能够协助我们日常工作、学习和创造的智能伙伴。随着ChatGPT 3.5和4.0版本的推出&#xff0c;其功能和应用范围…