缓存菜品操作

一:问题说明

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

二:实现思路 

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

缓存逻辑分析:

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

 三:具体的代码实现:

DishControll层(用户端):

我们需要在dishcontrol层加入缓存处理

  1. 注入redis
  2. 构造redis的key(根据我们上面的规则,redis中的key是为dish_ + 分类的id)
  3. 查询redis中是否有这个菜品
  4. 如果有,直接返回
  5. 如果没有,请求数据库,并且把这个菜品放到redis中
package com.sky.controller.user;import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.result.PageResult;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController("userDishController")
@RequestMapping("/user/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate RedisTemplate redisTemplate;/*** 根据分类id查询菜品* @param categoryId* @return*/@GetMapping("/list")@ApiOperation("根据分类id查询菜品")public Result<List<DishVO>> selectById(Long categoryId){log.info("根据分类id查询菜品:{}",categoryId);//构造redis中的key ,规则:dish_分类idString key = "dish_" + categoryId;//查询redis中是否又菜品数据List<DishVO> dishVOList = (List<DishVO>) redisTemplate.opsForValue().get(key);if(dishVOList != null|| dishVOList.size()>0){//如果存在,直接返回,不用查询数据库return Result.success(dishVOList);}Dish dish = new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE);/*这里的dish对象的作用就是充当一个判断条件我们返回的是一个List<DishVO>对象,那这个对象的条件是什么呢?是:这个dish的分类id和这个categoryId相等,并且呢,还得是在起售的产品*/List<DishVO> list = dishService.listWithFlavor(dish);//如果不存在,查询数据库,将查询到的数据放到redis中redisTemplate.opsForValue().set(key,list);return Result.success(list);}
}

 清理缓存:

上面的操作有一个很大的问题就是,如果我们修改了数据库里面的数据,怎么同步到redis中

这就涉及到这个请求缓存的操作了

我们的解决方法是在服务端DishControll层(因为客户肯定不可能修改我的数据,只有客户端可以)进行清理缓存的操作。

那这个时候又要具体分析了,什么样的方法需要清理缓存,是不是对数据库能进行修改的操作嘞

(增删改)

所以我们在dishcontroll层对这三类方法采用的方法是:

只要你对这个数据库进行了操作,我们直接把相关的缓存全部删掉

 DishControll层(服务端):

package com.sky.controller.admin;import com.github.pagehelper.Page;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.result.PageResult;
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.*;import java.util.ArrayList;
import java.util.List;
import java.util.Set;@RestController("adminDishController")
@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.insert(dishDTO);//清理缓存数据String pattern = "dish_"+dishDTO.getCategoryId();cleanCache(pattern);return Result.success();}/*** 分页查询菜品* @param dishPageQueryDTO* @return*/@GetMapping("/page")@ApiOperation("分页查询菜品操作")public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){log.info("分页查询菜品");PageResult pageresult = dishService.page(dishPageQueryDTO);return Result.success(pageresult);}/*** 批量删除菜品* @param ids* @return*/@DeleteMapping@ApiOperation("批量删除菜品")public Result delete(@RequestParam List<Long> ids){log.info("批量删除菜品:{}",ids);dishService.deletebatch(ids);//清理缓存数据String pattern = "dish_*";cleanCache(pattern);return Result.success();}/*** 根据id查询菜品* @param id* @return*/@GetMapping("/{id}")@ApiOperation("根据id查询菜品接口")public Result<DishVO> selectById(@PathVariable Long id){log.info("根据id查询菜品:{}",id);DishVO dishVO = dishService.selectById(id);return Result.success(dishVO);}/*** 修改菜品* @param dishDTO* @return*/@PutMapping@ApiOperation("修改菜品接口")public Result update(@RequestBody DishDTO dishDTO){log.info("修改菜品:{}",dishDTO);dishService.updateWithFlavor(dishDTO);//清理缓存数据String pattern = "dish_*";cleanCache(pattern);return Result.success();}/*** 菜品起售停售* @param status* @param id* @return*/@PostMapping("/status/{status}")@ApiOperation("菜品起售停售")public Result<String> startOrStop(@PathVariable Integer status, Long id){dishService.startOrStop(status,id);//清理缓存数据String pattern = "dish_*";cleanCache(pattern);return Result.success();}/*** 清理缓存* @param pattern*/private void cleanCache(String pattern){final Set keys = redisTemplate.keys(pattern);redisTemplate.delete(keys);}
}

四:Spring Cache框架:

Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能

Spring Cache中的常用注解:

Spring Cache入门小程序:

 @EnableCaching注解:

直接加在启动类上就行。

@Slf4j
@SpringBootApplication
@EnableCaching//启动缓存注解
public class CacheDemoApplication {public static void main(String[] args) {SpringApplication.run(CacheDemoApplication.class,args);log.info("项目启动成功...");}
}
 @CachePut注解:

(cacheput这个注解一般加在插入数据的方法上)

    @PostMapping@CachePut(cacheNames = "userNames",key = "#user.id")public User save(@RequestBody User user){userMapper.insert(user);return user;}

 这里的cacheNames其实就是这个缓存的名字。

key的生成:cacheNames::#user.id

我们这个使用的时候这个返回值的id,

    @Insert("insert into spring_cache_demo.user(name,age) values (#{name},#{age})")@Options(useGeneratedKeys = true,keyProperty = "id")void insert(User user);

这里需要注意的是,我们需要在mapper层中的插入方法下加入将id返回这个一个选项功能。

因为id是自增的,所以不一定要从前端传。 

@Cacheable注解:
    @GetMapping@Cacheable(cacheNames = "userNames",key = "#id")public User getById(Long id){User user = userMapper.getById(id);return user;}

这里的两个参数就和刚刚的@CachePut的参数一样就行。

下面是我查询了一个id为1的数据,因为id为1的数据还没放到缓存中,所以还是从数据库里面查的

 然后我查询了一个id为2的数据,控制台没有任何反应。

并且这个Cacheable注解还会把数据直接插入缓存中:

下面是我又查了一次id为1的数据。

控制台没有任何的反应

 @Cacheable 这个注解使用了一个代理对象的技术(AOP),

就是当你给controller层的方法加了这个Cacheable注解,其实这个框架就会创建一个代理对象,我们查询的数据会先被这个代理对象接收,如果这个代理对象没查到,才会交给这个方法来查。

具体的体现就是,如果这个数据在这个缓存中,就连这个select的方法都不会调用(用断点的方式可以测出)

 @CacheEvict注解:
    @DeleteMapping@CacheEvict(cacheNames = "userNames",key = "#id")public void deleteById(Long id){userMapper.deleteById(id);}

这个注解主要的作用就是帮我们清楚缓存,我们直接在发一条sql语句,同时能删除数据库中和redis中的数据。 

@CacheEvict(cacheNames = "setmealCache",allEntries = true)

如果指定这个allEntries = true,那就代表把所有的缓存都给删掉

 Spring Cache缓存套餐具体思路:

具体的实现思路如下:

  • 导入Spring Cache和Redis相关maven坐标
  • 在启动类上加入@EnableCaching注解,开启缓存注解功能
  • 在用户端接口SetmealController的 list 方法上加入@Cacheable注解
  • 在管理端接口SetmealController的 save、delete、update、startOrStop等方法上加入CacheEvict注解

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

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

相关文章

ACWing-186巴士-DFS

题目 原题链接&#xff1a;186. 巴士 - AcWing题库 oj:xmuoj | 最小化蒙德城的旅行者队伍 思路 本题因为n300&#xff0c;说明搜索深度很深&#xff0c;但是测试数量小于17&#xff0c;所以答案一定在比较浅的一个搜索深度中&#xff0c;于是可以利用迭代加深的处理方法迭代…

基于Springboot+Vue的Java项目-旅游网站系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

OpenNJet如何做到让用户永远在线

前言 最近看到了国内开源的一个名为OpenNJet的项目&#xff0c;有一个响亮的口号&#xff1a;“下一代云原生应用引擎”。 一下子就被吸引到了。 先看下官方对OpenNJet的介绍&#xff1a; OpenNJet 应用引擎是基于 NGINX 的面向互联网和云原生应用提供的运行时组态服务程序&…

红黑树(RBTree)认识总结

一、认识红黑树 1.1 什么是红黑树&#xff1f; 红黑树是一种二叉搜索树&#xff0c;与普通搜索树不同的是&#xff0c;在每个节点上增加一个“颜色”变量 —— RED / BLACK 。 通过对各个节点颜色的限制&#xff0c;确保从 根 到 NIL &#xff0c;没有一条路径会比其他路径长出…

借势母亲节h5小游戏的作用是什么

企业商家往往喜欢借势节日开展营销&#xff0c;母亲节作为5月的重要节日自然不可错过&#xff0c;不同行业商家都有自己开展互动想要实现的效果&#xff0c;如品牌宣传曝光、引流及渠道跳转等。 基于微信社交属性&#xff0c;有利于品牌发展&#xff0c;在【雨科】平台拥有多款…

基于web的物流管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

Backpropagation反向传播算法【总结】

概念介绍 Backpropagation本质上就是一个提升Gradient Descent效率的算法&#xff0c;核心在于其可以有效率地计算出一个偏移量来update下一组未知参数。 难点在于&#xff1a;Neural Network有很多层&#xff0c;而且每层参数都非常多&#xff0c;所以不能立即算出来该组未知…

【Linux网络编程】高级IO——五种IO模型

高级IO 1.什么是IO&#xff1f;什么是高效的IO&#xff1f;2.有那些IO的方式&#xff1f;这么多的方式&#xff0c;有那些是高效的&#xff1f;3.五种IO模型4.高级IO重要概念5.非阻塞IO 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x…

C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

信息泄露中的目录遍历,phpinfo,备份文件下载

一、目录遍历漏洞 1.什么是目录遍历漏洞 指的是在没有授权的情况下读取文件&#xff0c;某些情况下还可对服务器里的文件任意写入 2.目录遍历漏洞成因 网站配置存在缺陷&#xff0c;对输入目录缺少验证&#xff0c;没过滤../之类的目录跳转符&#xff0c;可通过提交目录跳转…

超详细——集成学习——Adaboost——笔记

资料参考 1.【集成学习】boosting与bagging_哔哩哔哩_bilibili 集成学习——boosting与bagging 强学习器&#xff1a;效果好&#xff0c;模型复杂 弱学习器&#xff1a;效果不是很好&#xff0c;模型简单 优点 集成学习通过将多个学习器进行结合&#xff0c;常可获得比单一…

AI绘画ComfyUI工作流安装教程,新手入门安装部署教程

ComfyUI 是专为 Stable Diffusion 打造的图形用户界面&#xff08;GUI&#xff09;&#xff0c;采用了基于节点的操作方式。用户可以通过连接不同的模块&#xff08;即节点&#xff09;来创建复杂的图像生成流程。这些节点涵盖了多样的功能&#xff0c;包括加载检查点模型、输入…

慧天卓特干旱监测系统:2023年云南最强冬春连旱分析

2023年开春以来&#xff0c;由于高温少雨&#xff0c;土壤失墒快&#xff0c;我国西南的云贵川渝等地区出现连续快速干旱&#xff0c;云南地区的干旱尤为严重。 2023年1月下旬至6月18日&#xff0c;云南平均降水量197.7毫米&#xff0c;为1961年以来历史同期最少&#xff0c;气…

生成requirements.txt文件

前言 对于Python项目&#xff0c;生成和使用requirements.txt是十分必要的。通过requirements.txt可以一次性保存和安装项目所需要的所有库。尤其是在复现github上的实验代码时。 方法1 常用的命令 pip freeze > requirements.txt然而这种方法并不好用&#xff0c;有时会…

什么是泛域名证书?与普通SSL证书有什么区别

随着互联网的发展&#xff0c;越来越多的网站开始使用SSL证书来保护用户的隐私和安全。在SSL证书中&#xff0c;泛域名SSL证书和普通域名证书是两种常见的类型。那么&#xff0c;什么是泛域名SSL证书&#xff0c;与普通域名证书有什么区别呢&#xff1f; 首先&#xff0c;我们来…

ChatGPT变懒原因:正在给自己放寒假!已被网友测出

ChatGPT近期偷懒严重&#xff0c;有了一种听起来很离谱的解释&#xff1a; 模仿人类&#xff0c;自己给自己放寒假了&#xff5e; 有测试为证&#xff0c;网友Rob Lynch用GPT-4 turbo API设置了两个系统提示&#xff1a; 一个告诉它现在是5月&#xff0c;另一个告诉它现在是1…

基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 遗传算法&#xff08;GA&#xff09;原理 4.2 BP神经网络原理 4.3 遗传优化BP神经网络结合应用 4.4 遗传算法简要改进 5.完整程序 1.程序功能描述 基于改进遗传优化的BP神经网络金融…

什么是影响力?HR招聘测评,如何考察候选人的影响力?

什么是影响力&#xff1f; 影响力也即是说服别人同你的观点&#xff0c;或者是潜移默化的改变他人&#xff0c;从而形成自我凝聚力&#xff0c;影响力可以推动某一个事务的进行。影响力尤其在管理型岗位上具有重要作用。 在百科中有如下定义&#xff1a;影响力是用别人乐于接受…

Python类方法探秘:从单例模式到版本控制

引言&#xff1a; 在Python编程中&#xff0c;类方法作为一种特殊的实例方法&#xff0c;以其独特的魅力在众多编程范式中脱颖而出。它们不仅提供了无需实例即可调用的便捷性&#xff0c;还在设计模式、版本控制等方面发挥着重要作用。本文将通过几个生动的示例&#xff0c;带您…

大厂常见算法50题-最小栈

专栏持续更新50道算法题&#xff0c;都是大厂高频算法题&#xff0c;建议关注, 一起巧‘背’算法! 文章目录 题目解法一 遍历找最小值&#xff08;不要求时间复杂度情况下&#xff09;解法二 辅助栈总结 题目 解法一 遍历找最小值&#xff08;不要求时间复杂度情况下&#xff0…