spring-cache框架使用笔记

spring-cache框架使用笔记

什么是spring-cache框架

spring-cache是spring框架中的一个缓存抽象层,
它提供了一种简便的方式来集成不同的底层缓存实现,
如内存缓存(concurrentMap/ehcache/caffeine)/分布式缓存(redis/couchbase)等
它简化了在app中使用缓存的逻辑,并提供了一组注解和API来实现缓存功能

springCache的特点和功能

1.声明性缓存
spring-cache通过注解的方式,允许开发者在方法级别上声明方法的结果要被缓存。
相关注解有@Cacheable 读取缓存+不存在则缓存
@CacheEvict 清除缓存
@CachePut 强制缓存
@Caching 复合功能注解==(@Cacheable+@CacheEvict+@CachePut)
2.缓存的透明性
spring-cache提供了一致的编程接口,
无论底层使用哪种缓存技术,开发者都可以使用相同的方式访问和管理缓存。
这可以使app轻松切换/替换不同的缓存实现技术,而无需更改业务代码3.注解定义缓存策略
可以使用注解@Cacheable/@CacheEvict/@CachePut 声明缓存的行为和策略
如声明缓存名称,缓存key
@Cacheable(cacheNames = "user", key = "#id")
会按照key=user::id缓存数据 (可以参见spring-cache-redis缓存效果)4.支持SpEL表达式
使用SpEL表达式,可以定义缓存的键、条件等。
这允许开发者根据方法参数、方法返回值等动态生成缓存键或决定是否应用缓存。
@Cacheable(cacheNames = "user", key = "#id",condition = "#id != null ")public UserDO getById(Long id) {returnuserRepo.findById(id).orElse(null);}
这个案例只有当id不为空时,才进行缓存
condition属性可以设置缓存的条件,如
#id >=100
#userInfo.id >10
#id%2!=0
等等,必须确保condition能正确返回布尔值,才能决定当前方法最终是否进行缓存

springCache+caffeine配合使用

什么是caffeine

caffeine是一种java内存缓存技术,支持多种缓存策略,
caffeine可以单独使用于普通java项目/springboot/springcloud项目,
这里引入caffeine来作为spring-cache存取缓存的数据区。

xml依赖配置

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.8.0</version></dependency>

yml配置

需要在application.yml配置spring-cache使用caffeine

spring:cache:type: caffeine #设置spring-cache框架使用caffeine存取数据  

caffeine配置类

package cn.test.cache;import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;@EnableCaching
@Configuration
public class CacheCfg {@Beanpublic CacheManager cacheManager(){//定义要缓存的caccheName有哪些CaffeineCacheManager caffeineCacheManager =new CaffeineCacheManager("user");//设置缓存配置caffeineCacheManager.setCaffeine(Caffeine.newBuilder()//初始容量10.initialCapacity(10)//最大容量200.maximumSize(200)//写入过期时间30s.expireAfterWrite(30, TimeUnit.SECONDS));return caffeineCacheManager;}
}

业务代码使用spring-cache相关注解

/*** @Cacheable注解标记一个方法时,spring会在执行方法之前,先检查缓存中是否已存在该方法的返回结果* 如果存在,则直接返回缓存的结果,不执行方法的实际逻辑* 如果不存在,则执行方法并将结果保存到缓存中*/@Cacheable(cacheNames = "user", key = "#id")public UserDO getById(Long id) {return userRepo.findById(id).orElse(null);}/*** @CacheEvict注解标记一个方法时,spring会在方法执行成功后,* 清空指定的缓存项,以确保下次访问时可以重新计算或查询最新的结果*/@CacheEvict(cacheNames = "user", key = "#id")public void delUser(Long id) {UserDO userDO = userRepo.findById(id).orElse(null);if (userDO != null) {userRepo.delete(userDO);}}/*** @CachePut注解标记一个方法时,spring会在方法执行后,* 将返回值放入指定的缓存中,* 以便将来的访问可以直接从缓存中获取结果,而不需要再执行方法的实际逻辑** @CachePut注解,适用于 创建新缓存 或 强制更新缓存 操作*/@CachePut(cacheNames = "user", key = "#userInfo.id")public UserDO addUser(UserDO userInfo) {return userRepo.save(userInfo);}/*** 执行updateUserInfo方法时,这里会按key 强制更新caffeine缓存*/@CachePut(cacheNames = "user", key = "#userInfo.id")public UserDO updateUserInfo(UserDO userInfo) {UserDO userDO = userRepo.findById(userInfo.getId()).orElse(null);if (userDO != null) {BeanUtils.copyProperties(userInfo,userDO);userRepo.save(userDO);}return userDO;}

springCache+redis配合使用

什么是redis

redis是一种分布式缓存技术,不限语言,C/S架构,支持可视化观测,
redis可以单独使用于普通java项目/springboot/springcloud项目/其他语言项目等,
这里引入redis来作为spring-cache框架存取缓存的数据区。

xml依赖配置

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.5.0</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

yml配置

spring:redis:# iphost: localhost# 端口6379port: 6379#密码,没有密码则不配置这一项password:#指定使用redis 16个库中的哪一个,不配置的话,默认配置为0database: 2lettuce:pool:min-idle: 0   #连接池最新空闲时间max-wait: -1ms  #最大等待时间max-active: 8   #最大活跃时间max-idle: 8    #最大空闲时间shutdown-timeout: 100ms  #连接池关闭超时时间timeout: 1000ms  #redis连接超时时间cache:type: redis     #设置spring-cache框架使用redis存取数据  

redis配置类

package cn.test.cache;import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@EnableCaching
@Configuration
public class RedisConfig {/*** 设置RedisTemplate使用的序列化器,* 这里使用string作为key的序列化,使用jackson作为value的序列化* @param redisConnectionFactory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();template.setKeySerializer(stringRedisSerializer);template.setValueSerializer(jsonSerializer);template.setHashKeySerializer(stringRedisSerializer);template.setHashValueSerializer(jsonSerializer);return template;}/*** 设置spring-cache使用redis后,要配置cacheManager缓存管理器** @param redisConnectionFactory* @return*/@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()//设置spring-cache缓存到redis的数据有效期是60s.entryTtl(Duration.ofSeconds(60))//key的序列化使用字符串.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))//value的序列化使用jackson.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer));return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();}}

业务代码使用spring-cache相关注解

 @Cacheable(cacheNames = "user", key = "#id")public UserDO getById(Long id) {return userRepo.findById(id).orElse(null);}@CacheEvict(cacheNames = "user", key = "#id")public void delUser(Long id) {UserDO userDO = userRepo.findById(id).orElse(null);if (userDO != null) {userRepo.delete(userDO);}}@CachePut(cacheNames = "user", key = "#userInfo.id")public UserDO addUser(UserDO userInfo) {return userRepo.save(userInfo);}@CachePut(cacheNames = "user", key = "#userInfo.id")public UserDO updateUserInfo(UserDO userInfo) {UserDO userDO = userRepo.findById(userInfo.getId()).orElse(null);if (userDO != null) {BeanUtils.copyProperties(userInfo,userDO);userRepo.save(userDO);}return userDO;}

使用RDM工具观察redis存储的数据

因为RedisCacheManager配置了使用jackson序列化,这里缓存数据值是以json格式存储到redis的。

可以观察到spring-cache存入redis的缓存有效期是60s (因为RedisCacheManager配置了60秒);

缓存的key是

user::1

缓存的value是

{"@class": "cn.test.orm.user.UserDO","id": 1,"account": "ewr3","pwd": "23r3r","remark": "23r3r","createTime": ["java.sql.Timestamp","2023-08-02 11:14:02"],"updateTime": ["java.sql.Timestamp","2023-08-02 11:14:02"],"isDel": 0
}

在这里插入图片描述

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

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

相关文章

go 如何知道一个对象是分配在栈上还是堆上?

如何判断变量是分配在栈&#xff08;stack&#xff09;上还是堆&#xff08;heap&#xff09;上&#xff1f; Go和C不同&#xff0c;Go局部变量会进行逃逸分析。如果变量离开作用域后没有被引用&#xff0c;则优先分配到栈上&#xff0c;否则分配到堆上。判断语句&#xff1a;…

tomcat

1. 简述静态网页和动态网页的区别。 静态网页是指在服务器存储的网页内容保持不变&#xff0c;不会根据用户的请求或其他条件而改变。它的内容是固定的&#xff0c;无法根据用户的不同需求进行个性化或实时更新。静态网页一般由HTML、CSS和JavaScript等静态资源组成&#xff0…

引入联合GraphQL以解决系统架构中的问题

随着使用需求的增长&#xff0c;用户群的扩大以及新功能的引入&#xff0c;让工程师按照业务的主要领域进行组织变得不可避免。当这些领域在单个实体&#xff08;如类、服务、应用程序或代码库&#xff09;的层面变得过于庞大难以管理时&#xff0c;引入联合GraphQL成为优化系统…

华为、阿里巴巴、字节跳动 100+ Python 面试问题总结(六)

系列文章目录 个人简介&#xff1a;机电专业在读研究生&#xff0c;CSDN内容合伙人&#xff0c;博主个人首页 Python面试专栏&#xff1a;《Python面试》此专栏面向准备面试的2024届毕业生。欢迎阅读&#xff0c;一起进步&#xff01;&#x1f31f;&#x1f31f;&#x1f31f; …

web前端框架Javascript之JavaScript 异步编程史

早期的 Web 应用中&#xff0c;与后台进行交互时&#xff0c;需要进行 form 表单的提交&#xff0c;然后在页面刷新后给用户反馈结果。在页面刷新过程中&#xff0c;后台会重新返回一段 HTML 代码&#xff0c;这段 HTML 中的大部分内容与之前页面基本相同&#xff0c;这势必造成…

vue列表全选反选

1、结果查看 2、 选中时添加样式 3、点击选择调用方法 4、全选反选调用方法

“ARTS挑战:探索技术,分享思考“

文章目录 前言一、学习的内容二、遇到的困难及解决办法三、学习打卡成果展示四、学习技巧的总结五、未来学习打卡计划后记 关于 ARTS 的释义 ● Algorithm: 每周至少做一个 LeetCode 的算法题 ● Review: 阅读并点评至少一篇英文技术文章 ● Tips: 学习至少一个技术技巧 ● Sha…

C语言自定义类型 — 结构体、位段、枚举、联合

前言 本期主要对通讯录三篇博客文章进行补充 通讯录文章&#xff1a;通讯录系列文章 对结构体进行详细介绍&#xff0c;其次讲解位段、枚举、联合体 文章目录 前言一、结构体1.什么是结构体2.结构声明2.1 声明格式2.2 如何声明&#xff08;代码演示&#xff09; 3.特殊声明3.1…

蓝桥杯上岸每日N题 第七期(小猫爬山)!!!

蓝桥杯上岸每日N题 第七期(小猫爬山)&#xff01;&#xff01;&#xff01; 同步收录 &#x1f447; 蓝桥杯上岸必背&#xff01;&#xff01;&#xff01;(第四期DFS) 大家好 我是寸铁&#x1f4aa; 冲刺蓝桥杯省一模板大全来啦 &#x1f525; 蓝桥杯4月8号就要开始了 &a…

NetApp 入门级全闪存系统 AFF A250:小巧而强大

NetApp 入门级全闪存系统 AFF A250&#xff1a;小巧而强大 作为 AFF A 系列中的入门级全闪存系统&#xff0c;AFF A250 不但可以简化数据管理&#xff0c;还能为您的所有工作负载提供令人惊叹的强劲动力&#xff0c;价格也平易近人。 AFF A250&#xff1a;您的新 IT 专家 AFF…

提高测试用例质量的6大注意事项

在软件测试中&#xff0c;经常会遇到测试用例设计不完整&#xff0c;用例没有完全覆盖需求等问题&#xff0c;这样往往容易造成测试工作效率低下&#xff0c;不能及时发现项目问题&#xff0c;无形中增加了项目风险。 因此提高测试用例质量&#xff0c;就显得尤为重要。一般来说…

paddlenlp:社交网络中多模态虚假媒体内容核查(代码篇)

初赛之baseline解读篇 一、模型框架图1、框架解读2、评价指标解读 二、代码功能1、数据集加载2、模型定义3、模型训练4、模型预测 三、写在最后 一、模型框架图 1、框架解读 第一列是输入&#xff0c;一部分是文本&#xff08;需核查文本、文本证据材料&#xff09;&#xff…