缓存优化----SpringCache

news2024/9/21 4:21:48

spring cache

  • spring Cache介绍

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

    Spring cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。

    cacheManager是spring提供的各种缓存技术抽象接口

    针对不同的缓存技术需要实现不同的cacheManager:

    CacheManager描述
    EhCacheCacheManager使用EhCache作为缓存技术
    GuavaCacheManager使用Google的GuavaCache作为缓存技术
    RedisCacheManager使用Redis作为缓存技术
  • spring cache常用注解

    注解说明
    @EnableCaching开启缓存注解功能
    @Cacheable在方法执行前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
    @CachePut将方法的返回值放到缓存中
    @CacheEvict将一条或多条数据从缓存中删除

    在Springboot项目中,使用缓存技术只需在项目中导入相关的缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存技术支撑即可

    例如:使用redis作为缓存技术,只需要导入spring data redis的maven坐标即可

  • spring cache使用方式

    在springboot项目中使用springcache的操作步骤(使用redis缓存技术):

    1. 导入maven坐标

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-cache</artifactId>
      </dependency>
      
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
      
    2. 配置application.yml

      redis:
        host: 172.17.2.94
        port: 6379
        password: root@123456
        database: 0
      cache:
        redis:
          time-to-live: 1800000 #设置缓存过期时间,可选
      
  1. 在启动类上加上@EnableCaching注解,开启缓存注解功能
  2. 在Controller的方法上加入@Cacheable、@CacheEvict等注解,进行缓存操作

userController

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private UserService userService;

    /**
     * CachePut:将方法返回值放入缓存
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     */
    @CachePut(value = "userCache",key = "#user.id")
    @PostMapping
    public User save(User user){
        userService.save(user);
        return user;
    }

    /**
     * CacheEvict:清理指定缓存
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     */
    @CacheEvict(value = "userCache",key = "#p0")//p0代表第一个参数,id是第一个参数等价
    //@CacheEvict(value = "userCache",key = "#root.args[0]")
    //@CacheEvict(value = "userCache",key = "#id")
    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id){
        userService.removeById(id);
    }

    //@CacheEvict(value = "userCache",key = "#p0.id")
    //@CacheEvict(value = "userCache",key = "#user.id")
    //@CacheEvict(value = "userCache",key = "#root.args[0].id")
    @CacheEvict(value = "userCache",key = "#result.id")
    @PutMapping
    public User update(User user){
        userService.updateById(user);
        return user;
    }

    /**
     * Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
     * value:缓存的名称,每个缓存名称下面可以有多个key
     * key:缓存的key
     * condition:条件,满足条件时才缓存数据
     * unless:满足条件则不缓存
     */
//    @Cacheable(value = "userCache",key = "#id",condition = "#result != null")//在源码中不能使用result这个参数,而unless可以使用result
    @Cacheable(value = "userCache",key = "#id",unless = "#result == null")
    @GetMapping("/{id}")
    public User getById(@PathVariable Long id){
        User user = userService.getById(id);
        return user;
    }

    @Cacheable(value = "userCache",key = "#user.id + '_' + #user.name")
    @GetMapping("/list")
    public List<User> list(User user){
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(user.getId() != null,User::getId,user.getId());
        queryWrapper.eq(user.getName() != null,User::getName,user.getName());
        List<User> list = userService.list(queryWrapper);
        return list;
    }
}

pom.cml

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

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

缓存套餐数据

  • 实现思路

前面我们已经实现了移动端套餐查看功能,对应的服务端方法为SetmealController的list方法,此方法会根据前端提交的查询条件进行数据库查询操作。在高并发的情况下,频道查询数据库会导致系统性能下降,服务端响应时间增长。现在需要对此方法进行缓存优化,提高系统性能。

具体的实现思路如下:

  1. 导入springcache和redis相关maven坐标

在这里插入图片描述

  1. 在application.yml中配置缓存数据的过期时间

在这里插入图片描述

  1. 在启动类上加入@EnableCaching注解,开启缓存注解功能

在这里插入图片描述

  1. 在SetmealController的list方法上加入@Cacheable注解

注意:返回值无法序列化 报错: DefaultSerializer requires a Serializable payload but received an object of type [com.itheima.reggie.common.R]

解决:

public class R<T> implements Serializable {//将R进行序列化不然进行SpringCache的时候会报错

报错:RedisCommandExecutionException: ERR wrong number of arguments for 'set' command

原因:redis版本原因,版本太低了,更换一个高点的redis版本就可以解决

在这里插入图片描述

  1. 在SetmealController的save和delete方法上加入CacheEvict注解
  • 代码改造
/*
* 删除套餐
* */
@DeleteMapping
@CacheEvict(value = "setmealCache",allEntries = true)//allEntries = true 该代码的意思是清除缓存中所有的数据
public R<String> delete(@RequestParam List<Long> ids){
    log.info("ids:{}",ids);
    setmealService.removeWithDish(ids);
    return R.success("套餐数据删除成功!!!!");
}
/*
    * 用户端套餐展示,根据条件查询套餐数据
    * */
    @GetMapping("/list")
    @Cacheable(value = "setmealCache",key = "#setmeal.categoryId+'_'+#setmeal.status")
    public R<List<Setmeal>> list(Setmeal setmeal){
        LambdaQueryWrapper<Setmeal>queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(setmeal.getCategoryId()!=null,Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.eq(setmeal.getStatus()!=null,Setmeal::getStatus,setmeal.getStatus());
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
        List<Setmeal> list = setmealService.list(queryWrapper);

        return R.success(list);
    }

  • 功能测试

在这里插入图片描述

问题(报错解决)

报错:RedisCommandExecutionException: ERR wrong number of arguments for 'set' command

原因:redis版本原因,版本太低了,更换一个高点的redis版本就可以解决

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

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

相关文章

springboot JWT 搭建授权服务器

目录 0 基本介绍 0.1 课程视频 0.2 架构逻辑图 0.2.1 登录JWT与授权服务器交互 0.2.2 登录成功后JWT与gateway-server交互 路由限制 1 JWT私钥公钥 1.1 安装git ->win系统右键 -> git bash here 1.2 生成私钥jks文件 1.3 用私钥jks文件解析出公钥 1.4 保存 BEGI…

造型简约的机箱,安装简单兼容性好,安钛克P20C体验

我们准备组装一台新主机的时候&#xff0c;机箱确实很重要&#xff0c;它决定了主机的整体风格和兼容性。我比较喜欢用中塔机箱&#xff0c;像是上个月我新装的主机&#xff0c;用的就是安钛克P20C&#xff0c;这款机箱的设计很简约&#xff0c;而且还有多种版本可选&#xff0…

C++——模板进阶

文章目录 &#x1f490;专栏导读&#x1f490;文章导读&#x1f337;类型模板参数&#x1f337;非类型模板参数&#x1f337;模板的特化&#x1f338;引例&#x1f338;函数模板的特化&#x1f338;类模板特化&#x1f33c;全特化 &#x1f338;偏特化&#x1f33c;部分特化&am…

【下载器篇】IDM下载器个性化设置

【下载器篇】IDM下载器个性化设置 IDM个性化设置—【蘇小沐】 文章目录 【下载器篇】IDM下载器个性化设置1.实验环境 &#xff08;一&#xff09;下载类型扩展UA默认值 &#xff08;二&#xff09;工具栏样式&#xff08;改风格&#xff09;3D Style样式 &#xff08;三&#…

2023.4.23 自注意力机制

一般都是单向量输入&#xff0c;但是如果多向量输入应该如何处理呢&#xff1f;引出自注意力机制 多向量输入可能会有多种输出&#xff0c;如果输入n个向量&#xff0c;输出n个向量表明这是sequence labeling&#xff0c;比如对于一个英文句子&#xff0c;每一个单词都判断是什…

c++11 标准模板(STL)(std::priority_queue)(二)

适配一个容器以提供优先级队列 std::priority_queue 定义于头文件 <queue> template< class T, class Container std::vector<T>, class Compare std::less<typename Container::value_type> > class priority_queue; priority_queu…

Windows下编译UHD

1.安装Visual Studio 2019,下载地址https://download.csdn.net/download/qq_36314864/87719209 2.安装cmake,下载地址https://download.csdn.net/download/qq_36314864/87719747 安装完成后记得C:\Program Files\cmake-3.22.1-windows-x86_64\bin添加到环境变量里面,或者安…

数据结构修炼:链表习题讲解!!!

题一&#xff1a;移除链表元素 我们可以看出这道题是让我们删除特定数据&#xff0c;我们可以用双指针来解这道题&#xff1a; 如果首元素为val&#xff0c;那么cur和head一起后移&#xff1a; 如果没有碰到val&#xff0c;那么就会cur后移&#xff0c;并且提前将cur传给perv&a…

如何避免美国ASP主机服务器崩溃和故障?

在当今数字化时代&#xff0c;网站是一个公司展示其业务的主要方式之一。因此&#xff0c;公司的在线业务应该始终保持高可用性和可靠性。ASP主机服务器是一种用于托管网站的服务器&#xff0c;其特点是可靠性高。但是&#xff0c;即使是最可靠的服务器也会遭受故障或崩溃。在本…

漏刻有时数据可视化大屏引导页设计(php原生开发、主背景图片更换、标题设置)

文章目录 1.引入外部js库2.HTML排版3.项目配置文件4.菜单图标自动匹配5.php与html混排6.CSS样式表7.添加/编辑信息8.生成配置文件 在制作数据可视化大屏时&#xff0c;尤其是在触摸屏演示时&#xff0c;需要开发和设计对应的数据大屏引导页。基于常见场景&#xff0c;单独开发数…

Unity API详解——Object类

Object类是Unity中所有对象的基类&#xff0c;例如GameObject、Component、Material、Shader、Texture、Mesh、Font等都是Object的子类。本博客介绍Object类的一些实例方法和静态方法。 一、Object类实例方法 在Object类中&#xff0c;涉及的实例方法主要有GetInstanceID方法…

Java基础学习(10)

Java基础学习 一、JDK8时间类1.1 Zoneld时区1.2 Instant时间戳1.3 ZonedDateTime1.4 DateTimeFormatter1.5 日历类时间表示1.6 工具类1.7 包装类JDK5提出的新特性Integer成员方法 二、集合进阶2.1 集合的体系结构2.1.1 Collection 2.2collection的遍历方式2.2.1 迭代器遍历2.2.…

RecycleView与TabLayout联动展示更多功能列表页面的实现

一.前言 对于更多功能页面&#xff0c;使用RecycleView与TabLayout联动方式实现是比较常见的&#xff0c;先上效果图&#xff08;请大佬们忽略gif的水印&#xff09; 单独使用TabLayout和RecycleView都是比较容易的&#xff0c;这里就不做举例了&#xff1b;gif中的列表实际上…

权限控制导入到项目中

在项目中应用 进行认证和授权需要前面课程中提到的权限模型涉及的7张表支撑&#xff0c;因为用户信息、权限信息、菜单信息、角色信息、关联信息等都保存在这7张表中&#xff0c;也就是这些表中的数据是进行认证和授权的依据。所以在真正进行认证和授权之前需要对这些数据进行…

( “树” 之 BST) 501. 二叉搜索树中的众数 ——【Leetcode每日一题】

二叉查找树&#xff08;BST&#xff09;&#xff1a;根节点大于等于左子树所有节点&#xff0c;小于等于右子树所有节点。 二叉查找树中序遍历有序。 ❓501. 二叉搜索树中的众数 难度&#xff1a;简单 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root…

Leetcode每日一题——“合并两个有序数组”

各位CSDN的uu们你们好呀&#xff0c;又到小雅兰的愉快题解时候啦&#xff0c;今天&#xff0c;我们的题目内容是合并两个有序数组&#xff0c;下面&#xff0c;让我们进入合并两个有序数组的世界吧 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,3,0,0,0], m 3, nums2 [2,…

C++内联/构造函数详解

内联函数 宏&#xff1a; 宏的优缺点&#xff1f; 优点&#xff1a; 1.增强代码的复用性。 2.提高性能。 缺点&#xff1a; 1.展开后会使得代码长度变长&#xff0c;使可执行程序变大 2.不方便调试宏。&#xff08;因为预编译阶段进行了替换&#xff09; 3.导致代码可读性差…

Python 查看数据常用函数

Python 查看数据常用函数&#xff08;以 iris 数据集为例&#xff09; 1、查看前后几行数据&#xff1a;head 和 tail2、查看数据基本信息&#xff1a;info3、查看数据统计信息&#xff1a;describe 查看数据可以用很多函数&#xff0c;这里就挑选几个最常用的进行简单展示&…

SpringBoot自动配置原理、手写一个xxx-spring-boot-starter

SpringBoot的自动配置是&#xff1a;当项目中使用了一个第三方依赖&#xff0c;如何将第三方依赖中的Bean加载到Spring的IOC容器中&#xff0c;我们就可以做到无需额外的配置&#xff0c;直接使用第三方jar中的Bean。 SpringBoot的理念是“约定大于配置”&#xff0c;只要按照S…

【下载器篇】IDM下载记录分析(简)

【下载器篇】IDM下载记录分析&#xff08;简&#xff09; IDM下载记录分析-未完待续—【蘇小沐】 文章目录 【下载器篇】IDM下载记录分析&#xff08;简&#xff09;1.实验环境 &#xff08;一&#xff09;IDM下载记录分析-未完待续临时文件夹下载痕迹 总结 1.实验环境 系统版…