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.rhkb.cn/news/73276.html

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

相关文章

哈工大计算机网络课程网络安全基本原理之:身份认证

哈工大计算机网络课程网络安全基本原理之&#xff1a;身份认证 在日常生活中&#xff0c;在很多场景下我们都需要对当前身份做认证&#xff0c;比如使用密码、人脸识别、指纹识别等&#xff0c;这些都是身份认证的常用方式。本节介绍的身份认证&#xff0c;是在计算机网络安全…

【机器学习】分类算法 - KNN算法(K-近邻算法)KNeighborsClassifier

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;零基础快速入门人工智能《机器学习入门到精通》 K-近邻算法 1、什么是K-近邻算法&#xff1f;2、K-近邻算法API3、…

Tessy 4.3.18

Tessy 4.3.18 windows 2692407267qq.com&#xff0c;更多内容请见http://user.qzone.qq.com/2692407267/

使用GGML和LangChain在CPU上运行量化的llama2

Meta AI 在本周二发布了最新一代开源大模型 Llama 2。对比于今年 2 月发布的 Llama 1&#xff0c;训练所用的 token 翻了一倍&#xff0c;已经达到了 2 万亿&#xff0c;对于使用大模型最重要的上下文长度限制&#xff0c;Llama 2 也翻了一倍。 在本文&#xff0c;我们将紧跟趋…

【Linux】Linux服务器连接百度网盘:实现上传下载

【Linux】Linux服务器连接百度网盘&#xff1a;实现上传下载 文章目录 【Linux】Linux服务器连接百度网盘&#xff1a;实现上传下载1. 前言2. 具体过程2.1 pip 安装所需包2.2 认证&#xff08;第一次连接需要认证&#xff09;2.3 下载所需文件或者目录2.4 其他指令使用2.5 注意…

node.js 爬虫图片下载

主程序文件 app.js 运行主程序前需要先安装使用到的模块&#xff1a; npm install superagent --save axios要安装指定版,安装最新版会报错&#xff1a;npm install axios0.19.2 --save const {default: axios} require(axios); const fs require(fs); const superagent r…

Java导出数据到Excel

Java导出数据到Excel分3步处理 1、构建Workbook 数据 2、设置Workbook 格式 3、导出到Excel 1、构建Workbook 数据 public static void buildData(Workbook wb, List<Person> list) {Sheet sheetName wb.createSheet("sheetName");Row row sheetName.creat…

每日一题8.2 2536

2536. 子矩阵元素加 1 给你一个正整数 n &#xff0c;表示最初有一个 n x n 、下标从 0 开始的整数矩阵 mat &#xff0c;矩阵中填满了 0 。 另给你一个二维整数数组 query 。针对每个查询 query[i] [row1i, col1i, row2i, col2i] &#xff0c;请你执行下述操作&#xff1a;…

NAS私有云存储 - 搭建Nextcloud私有云盘并公网远程访问

文章目录 摘要视频教程1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文…

【数据结构】单链表

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;数据结构 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、什么是链表 1.1链表的概念及结构 1.2单链表的结构 二、链表的实现 …

[JavaScript游戏开发] 2D二维地图绘制、人物移动、障碍检测

系列文章目录 第一章 2D二维地图绘制、人物移动、障碍检测 第二章 跟随人物二维动态地图绘制、自动寻径、小地图显示(人物红点显示) 第三章 绘制冰宫宝藏地图、人物鼠标点击移动、障碍检测 第四章 绘制Q版地图、键盘上下左右地图场景切换 文章目录 系列文章目录前言一、列计划…

SpringBoot中间件—ORM(Mybatis)框架实现

目录 定义 需求背景 方案设计 代码展示 UML图 实现细节 测试验证 总结 源码地址&#xff08;已开源&#xff09;&#xff1a;https://gitee.com/sizhaohe/mini-mybatis.git 跟着源码及下述UML图来理解上手会更快&#xff0c;拒绝浮躁&#xff0c;沉下心来搞 定义&#x…

最新版本mac版Idea 激活Jerbel实现热部署

1.环境准备 1.安装docker desktop 客户端创建本地服务 2.创建guid 3.随便准备一个正确格式的邮箱 2.具体操作 1.通过提供的镜像直接搭建本地服务 docker pull qierkang/golang-reverseproxy docker run -d -p 8888:8888 qierkang/golang-reverseproxy2.guid 通过如下网址直…

干掉 “重复代码”,这三种方式绝了!

来源&#xff1a;我是程序汪 软件工程师和码农最大的区别就是平时写代码时习惯问题&#xff0c;码农很喜欢写重复代码而软件工程师会利用各种技巧去干掉重复的冗余代码。 业务同学抱怨业务开发没有技术含量&#xff0c;用不到设计模式、Java 高级特性、OOP&#xff0c;平时写…

2.2 身份鉴别与访问控制

数据参考&#xff1a;CISP官方 目录 身份鉴别基础基于实体所知的鉴别基于实体所有的鉴别基于实体特征的鉴别访问控制基础访问控制模型 一、身份鉴别基础 1、身份鉴别的概念 标识 实体身份的一种计算机表达每个实体与计算机内部的一个身份表达绑定信息系统在执行操作时&a…

AI 绘画Stable Diffusion 研究(二)sd模型ControlNet1.1 介绍与安装

部署包作者:秋葉aaaki 免责声明: 本安装包及启动器免费提供 无任何盈利目的 大家好&#xff0c;我是风雨无阻。 众所周知&#xff0c;StableDiffusion 是非常强大的AI绘图工具&#xff0c;需要详细了解StableDiffusion的朋友&#xff0c;可查看我之前的这篇文章&#xff1a; …

剑指offer48.最长不含重复字符的子字符串

我一开始的想法是创建一个大小为26的int数组&#xff0c;下标为0对应的是‘a&#xff0c;25对应的是’z&#xff0c;然后一开始都赋为-1&#xff0c;用一个for循环从头遍历这个字符串&#xff0c;通过char c s.charAt(i)获得字符&#xff0c;然后c-97&#xff0c;就是它对应的…

新抗原预测的计算工作流程

参考文献&#xff1a;Xie N, Shen G, Gao W, Huang Z, Huang C, Fu L. Neoantigens: promising targets for cancer therapy. Signal Transduct Target Ther. 2023 Jan 6;8(1):9. doi: 10.1038/s41392-022-01270-x. PMID: 36604431; PMCID: PMC9816309. 文章目录 *新抗原预测的…

小程序开发趋势:探索人工智能在小程序中的应用

第一章&#xff1a;引言 小程序开发近年来取得了快速的发展&#xff0c;成为了移动应用开发的重要一环。随着人工智能技术的飞速发展&#xff0c;越来越多的企业开始探索如何将人工智能应用于小程序开发中&#xff0c;为用户提供更智能、便捷的服务。本文将带您一起探索人工智能…

uniapp uview文件上传的文件不是文件流,该如何处理?用了uni.chooseImage预览功能要如何做

在使用uniapp开发&#xff0c;运用的ui是用uview&#xff0c;这边需要做一个身份认证&#xff0c;如下图 使用的是uview的u-upload组件&#xff0c;可是这个组件传给后端的不是文件流 后端接口需要的是文件流格式&#xff0c;后面使用了uniapp的选择图片或者拍照的api&#x…