基于SpringCache实现数据缓存

news2024/11/17 23:31:03

SpringCache

SpringCache是一个框架实现了基本注解的缓存功能,只需要简单的添加一个@EnableCaching 注解就能实现缓存功能

  • SpringCache框架只是提供了一层抽象,底层可以切换CacheManager接口的不同实现类即使用不同的缓存技术,默认的实现是ConcurrentMapCacheManager
  • ConcurrentMapCacheManager是基于内存存储数据的,所以重启服务后缓存数据就会消失
CacheManger描述
EhCacheCacheManager使用EhCache作为缓存技术
GuavaCacheManager使用Googke的GuavaCache作为缓存技术
RedisCacheManager使用Rdis作为缓存技术

环境准备

第一步: 定义实体类User且实现序列化接口

@Data
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    private String name;
    private int age;
    private String address;
}

第二步: 定义Mapper接口

@Mapper
public interface UserMapper extends BaseMapper<User>{
}

第三步: 定义UserService接口及其实现类

public interface UserService extends IService<User> {
    
}

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
    
}

第四步: 定义接口

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    // 默认的实现是ConcurrentMapCacheManager
    @Autowired
    private CacheManager cacheManager;
    
    @Autowired
    private UserService userService;
}

第五步: 开启缓存注解功能

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

SpringCache常用注解

因为缓存的数据key一定是唯一的,所以key支持SpEL表达式来动态的计算key(条件判断也支持SpEL表达式)

  • #result: 代表方法的返回值,如#result.id表示获取返回值对象的id属性值作为key
  • #root: 代表整个方法对象,如#root.args[0].id表示获取方法的第一个参数的id属性值作为key
  • #p[i]: 代表方法的参数,如p[0].id表示获取方法的第一个参数的id属性值作为key
  • #方法参数名: 代表方法的参数,如#user.id获取参数user对象的id属性值作为key

condition和unless的区别

  • condition: 表示满足条件才进行缓存,不支持SpEL表达式中的#result
  • unless: 表示满足条件不进行缓存,支持SpEL表达式中的#result
注解说明
@EnableCaching开启缓存注解功能
@Cacheable在方法执行前spring先查看缓存中是否有数据,如果有数据则直接返回缓存数据;若没有数据调用方法并将方法返回值放到缓存中(查询方法)
@CachePut将方法的返回值放到缓存中(适合新增的方法)
@CacheEvict将一条或者多条数据从缓存中删除(适合删除和更新的方法啊)

@CachePut(新增)

@CachePut主要针对方法配置,能够根据方法的请求参数将方法的返回值进行缓存,每次都会触发真实方法的调用

注解说明举例
value指定缓存的名称必须指定至少一个@Cacheable(value=”mycache”)或者@Cacheable(value=(“cache7”, “cache2”]
key指定缓存的key(可以为空),但必须是动态唯一的,表示某类缓存中的一个具体数据@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

测试新增的方法将方法的返回值进行缓存

在这里插入图片描述

@CachePut(value="userCache",key="#user.id")
@PostMapping
public User save(User user){
    userService.save(user);
    return user;
}

查看ConcurrentMapCacheManager中缓存的结果

在这里插入图片描述

@CachEvict(删除)

@CachEvict主要针对方法配置,能够根据一定的条件将缓存中的数据进行清空

注解说明举例
value缓存的名称必须指定且至少一个@Cacheable(value=”mycache”)或者@Cacheable(value={“cache1”, “cache2”]
key指定缓存的key(可以为空),但必须是动态唯一的@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
allEntries是否清空某类缓存下的所有数据,默认为false@CachEvict(value=”testcache”,allEntries=true)
beforelnvocation是否在方法执行前就清空,缺省为false,如果指定为true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存@CachEvict(value=”testcache”, beforelnvocation=true)

测试删除的方法清楚缓存中指定的key

在这里插入图片描述

@CachEvict(value="userCache",key="#user.id")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){
    userService.removeById(id);
}

测试更新的方法清楚缓存中指定的key

在这里插入图片描述

@CachEvict(value="userCache",key="#id")
@PutMapping
public User update(User user){
    userService.updateById(user);
    return user;
}

@Cacheable(查询)

@Cacheable注解主要针对方法配置,如果缓存中没有数据能够根据方法的请求参数对方法结果进行缓存,如果缓存中有数据则不会调用方法

  • 如果查询的数据在数据库中也查询不到则会缓存一个null,这样下次再查询这个数据时直接返回null,避免缓存穿透
注解说明举例
value指定缓存的名称表示一类缓存,每个缓存名称下可以存储多个key@Cacheable(value=”mycache”)或者@Cacheable(value=(“cache7”, “cache2”]
key(唯一)指定缓存数据的key(可以为空),表示某类缓存中的一个具体数据@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
unless指定缓存的条件(可以为空)返回true或者false,满足条件不进行缓存@Cacheable(value=”testcache”,unless=”#userName.length()>2”)

测试根据id查询的方法,如果缓存中没有数据则将方法返回值进行缓存,如果缓存中有对应数据则不调用方法直接返回缓存的数据

在这里插入图片描述

@Cacheable(value="userCache",key="#id")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
    User user = userService.getById(id);
    return user;
}
// 查询结果为null不缓存,condition不支持#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")//查询条件和id和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;
}

查询缓存的结果

在这里插入图片描述

使用SpringCache基于redis

使用步骤

第一步: 在SpringBoot项目中使用缓存技术只需要在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存技术支持即可

  • 如果想使用SpringCache的基本功能只需要导入spring-context依赖即可(导入spring-boot-starter-web会自动传递)
<!--使用Redis作为缓存技术,里面包含CacheManager接口的实现类-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--对SpringCache中CacheManager接口的实现类进行了扩展-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

第二步: 在application.yml文件中配置redis相关的配置

spring:
  redis:
    host: 101.XXX.XXX.160 #redis服务所在地址
    password: root
    port: 6379
    database: 0
  cache:
    redis:
      time-to-live: 3600000 #设置缓存有效期为一小时(单位毫秒),如果不设置则一直存活
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    // 底层实现是RedisCacheManager
    @Autowired
    private CacheManager cacheManager;
    
    @Autowired
    private UserService userService;
}

第三步: 在启动类上加@EnableCaching注解表示开启缓存注解功能

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

第四步: 在Controller的方法上加上@Cacheable,@CachePut,@CacheEvict缓存注解进行缓存操作

在这里插入图片描述

// 查询结果为null不缓存,condition不支持#result
@Cacheable(value="userCache",key="#id",unless="#result==null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
    User user = userService.getById(id);
    return user;
}

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

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

相关文章

Redisson分布式锁解决方案

官方地址 官网: https://redisson.org github: https://github.com/redisson/redisson 基于setnx实现的分布式锁存在的问题 redisson分布式锁原理 不可重入: 利用hash结构记录线程id和重入次数不可重试: 利用信号量和PubSub功能实现等待、唤醒, 获取锁失败的重试机制超时释放…

监听抖音直播间的评论并实现存储

监听抖音直播间评论&#xff0c;主要是动态监听dom元素的变化&#xff0c;如果评论是图片类型的&#xff0c;获取alt的值 主要采用的是MutationObserver&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver index.js如下所示:function getPL() {…

29网课交单平台源码最新修复全开源版本

去除论文编辑 去除强国接码 修复上级迁移 修复聚合登录 修复支付不回调 优化支付接口兼容码/易支付 优化MySQL表&#xff0c;提高网页加载速度 下载地址&#xff1a;https://pan.xunlei.com/s/VNstLrJaRtbvDyovPQ-CbISOA1?pwd622t#

数字人基础 | 3D手部参数化模型2017-2023

楔子: 2017年年底的泰国曼谷, SIGGRAPH Asia会议上, 来自马普所的 Javier Romero, Dimitrios Tzionas(两人都是 Michael J. Black的学生)发布了事实性的手部参数化模型标准: MANO [1]。 MANO的诞生意味着 Michael J. Black团队在继人体参数化模型 SMPL后, 事实性的将能够表达人…

【正则表达式】正则表达式里使用变量

码 const shuai No My Name Is ShuaiGe.match(new RegExp(shuai, gi)); //↑↑↑↑↑↑↑↑ //等同于 //↓↓↓↓↓↓↓↓ /No/.test(My Name Is ShuaiGe)用作领域 搜索的字符动态改变&#xff0c;例如↓模糊搜索例&#xff1a; 一个文本宽&#xff0c;输入文本模糊搜索用户…

【哈希映射】【 哈希集合】 381. O(1) 时间插入、删除和获取随机元素 - 允许重复

作者推荐 视频算法专题 本文涉及知识点 哈希映射 哈希集合 LeetCode 381. O(1) 时间插入、删除和获取随机元素 - 允许重复 RandomizedCollection 是一种包含数字集合(可能是重复的)的数据结构。它应该支持插入和删除特定元素&#xff0c;以及删除随机元素。 实现 Randomiz…

【漏洞复现】金和OA viewConTemplate.action RCE漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

XIAO ESP32S3部署Edge Impulse模型

在上一篇文章中我们介绍了如何使用edge impulse训练一个图片分类模型并导出arduino库文件。在这篇文章中我们将介绍如何在esp32s3中部署这个训练好的图片分类模型。 添加进Arduino库 有两种方法将下载的文件添加进Arduino库。 在Arduino IDE程序中&#xff0c;转到项目选项卡…

php apache 后台超时设置

最近在写一个thinkphp项目的时候&#xff0c;发现Ajax从后端请求数据时间比较长&#xff0c;大概需要45秒左右&#xff0c;但是一旦请求时间超过40s&#xff0c;页面就会超时500了&#xff0c;一开始以为是ajax请求时间不能太长&#xff0c;后来将Ajax请求改为同步且timeout设置…

景联文科技:提供行业垂直大模型训练数据

近年来&#xff0c;以大模型为代表的人工智能技术已成为国家科技实力竞争的焦点。其中垂直大模型作为重要方向&#xff0c;在相关政策引导及市场需求的驱动下&#xff0c;已展现出较强的发展活力。 行业垂直大模型是针对特定行业的需求和场景进行深度定制的。这意味着模型在训练…

软考高级:需求变更管理过程概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【ARM】MDK在programming algorithm界面添加FLM

【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 解决在programming algorithm界面中无法添加想要的Flash编程算法的问题 2、 问题场景 在对于Debug进行Flash Download进行配置的时候&#xff0c;在programming algorithm界面中有对应的Flash编程算法。可以通过…

【python】anaconda安装过程

【运行环境】Windows11 文章目录 一、anaconda下载二、anaconda安装三、环境变量配置四、测试环境变量是否配置成功五、总结 一、anaconda下载 1、输入网址“https://www.anaconda.com”进入Anaconda官网。 2、找到【Free Download】点击进入&#xff1a; 3、点击对应系统的…

spring源码环境搭建问题解决

源码搭建需要提前准备的环境 jdk环境变量配置 gradle环境变量配置&#xff08;gradle安装配置详细教程(windows环境)_windows安装gradle-CSDN博客&#xff09; spring5.2.x jdk1.8 gradle5.6.4(源码对应的gradle版本查看路径&#xff0c;在源码中找对应文件配置&#xff1a…

leetcode一天一题-第1天

为了增加自己的代码实战能力&#xff0c;希望通过刷leetcode的题目&#xff0c;不断提高自己&#xff0c;增加对代码的理解&#xff0c;同时开拓自己的思维方面。 题目名称&#xff1a;两数之和 题目编号&#xff1a;1 题目介绍&#xff1a; 给定一个整数数组 nums 和一个整数…

基于恒功率PQ控制的三电平并网逆变器MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介 三相 T 型三电平逆变器电路如图所示&#xff0c;逆变器主回路由三个单相 T 型逆变器组成。 直流侧输入电压为 UPV&#xff0c;直流侧中点电位 O 设为零电位&#xff0c;交流侧输出侧是三相三线制连…

【快速上手ProtoBuf】proto 3 语法详解

1 &#x1f351;字段规则&#x1f351; 消息的字段可以⽤下⾯⼏种规则来修饰&#xff1a; singular &#xff1a;消息中可以包含该字段零次或⼀次&#xff08;不超过⼀次&#xff09;。 proto3 语法中&#xff0c;字段默认使⽤该规则。repeated &#xff1a;消息中可以包含该…

【Java设计模式】十九、中介者模式

文章目录 1、中介者模式2、案例3、总结 1、中介者模式 如图&#xff1a; 同事类之间关联较多时&#xff0c;整体出现网状结构&#xff0c;耦合度极高。一个对象一变动&#xff0c;好多对象都得改。若变为右边的星形结构&#xff0c;则一个类的变动&#xff0c;只影响自身与中介…

滴滴 Flink 指标系统的架构设计与实践

毫不夸张地说&#xff0c;Flink 指标是洞察 Flink 任务健康状况的关键工具&#xff0c;它们如同 Flink 任务的眼睛一般至关重要。简而言之&#xff0c;这些指标可以被理解为滴滴数据开发平台实时运维系统的数据图谱。在实时计算领域&#xff0c;Flink 指标扮演着举足轻重的角色…

vue中ref 根据多选框所选数量,动态地变换box的高度

查看本专栏目录 关于作者 还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#x…