SpringBoot整合SpringCache缓存

SpringBoot整合SpringCache使用缓存

文章目录

    • SpringBoot整合SpringCache使用缓存
    • 1.介绍
    • 2.SpringBoot整合
      • 1.导入xml依赖
      • 2.配置yml
      • 3.使用@EnableCaching启用SpringCache
      • 4.@Cacheable
      • 5.@CachePut
      • 6.@CacheEvict
      • 7. @Caching
      • 8.@CacheConfig
    • 3.其他属性配置
        • 1.`keyGenerator` 属性
        • 2. `cacheManager` 属性
        • 3.`cacheResolver` 属性
        • 4.CacheManagerCustomizer

1.介绍

Spring Cache 提供了 CacheCacheManager 接口来统一管理不同的缓存技术。Cache 是缓存的抽象,CacheManager 负责管理多个 Cache 实例。Spring Cache 支持多种缓存实现,包括:

  • ConcurrentHashMap:默认的缓存实现,适用于简单的本地缓存。
  • Redis:基于 Redis 的分布式缓存,适用于高并发场景。
  • Ehcache:符合 JSR-107 标准的缓存实现,支持二级缓存。
  • Caffeine:基于 Java 8 的高性能缓存库,适用于需要高性能的场景。
  • JSR-107:支持 JSR-107 标准的缓存实现。

2.SpringBoot整合

本文基于springboot2.7版本测试

1.导入xml依赖

        <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.配置yml

spring:cache:cache-names: usertype: redisredis:#缓存前缀key-prefix: moshangshang_#是否启用缓存统计信息。enable-statistics: false#是否允许缓存 null 值。cache-null-values: true#写入 Redis 时是否使用 key prefix。use-key-prefix: trueredis:port: 6379host: 127.0.0.1password: rootlettuce:pool:max-active: 20 #连接池最大连接数(使用负值表示没有限制)max-idle: 8   #连接池中的最大空闲连接min-idle: 5   # 连接池中的最小空闲连接timeout: 6000   #连接超时时长(毫秒)

如果cache-null-values:属性启用不能缓存null值,则缓存null时会抛出下方异常

java.lang.IllegalArgumentException: Cache 'user' does not allow 'null' values. Avoid storing null via '@Cacheable(unless="#result == null")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.

cache-names属性说明:

用于管理全的缓存key的全局配置,多个用逗号分割,比如 cache-names: user; use-key-prefix: false,则表示 @Cacheable(cacheNames = "user“)之类的注解不会使用key-prefix指定的缓存前缀,未配置的缓存名称则采用默认全局配置

3.使用@EnableCaching启用SpringCache

@SpringBootApplication
@EnableCaching
public class CacheApplication {public static void main(String[] args) {SpringApplication.run(CacheApplication.class, args);}
}

4.@Cacheable

@Cacheable 用于标记方法或类,表示该方法的返回值可以被缓存。
当方法执行前,Spring 会检查缓存中是否存在相同 key 的缓存元素,如果存在则直接返回,否则执行方法并将结果存入缓存。

@Cacheable 的方法必须为 public:如果方法不是 public 的,Spring 无法通过代理来访问缓存。

  • value 或 cacheNames:指定缓存的名称,可以是单个字符串或字符串数组。
  • key:指定缓存的键,可以使用 SpEL 表达式来定义。
  • condition:指定缓存的条件,只有当条件为 true 时,才会从缓存中获取结果。
  • unless:指定不将结果放入缓存的条件,即使结果存在,也不会被缓存。
  • sync:是否使用同步方式获取缓存,避免多个线程同时执行方法。
  • 在某些场景下,需要确保缓存和数据库的一致性,可以使用 @Cacheable 的 sync 属性来启用同步更新。且在多线程环境下确保只有一个线程执行查询。
   /*** 根据id查询用户信息* 生成的key为moshangshang_user::38*/@GetMapping("/query/{id}")@Cacheable(cacheNames = "user",key = "#id",unless = "#result == null")public User getById(@PathVariable Long id){return userService.getById(id);}

5.@CachePut

@CachePut 用于标记方法,表示每次调用该方法时都会执行并存入缓存。

它总是会执行方法,并将结果添加到缓存中,不会检查缓存中是否存在相同 key 的缓存元素。

  • value 或 cacheNames:指定缓存的名称,可以是单个字符串或字符串数组。
  • key:指定缓存的键,可以使用 SpEL 表达式来定义。
  • condition:指定缓存的条件,只有当条件为 true 时,才会从缓存中获取结果。
  • unless:指定不将结果放入缓存的条件,即使结果存在,也不会被缓存。
    @PostMapping("/save")@CachePut( key = "#user.id")public User updateUser(User user) {userService.saveOrUpdate(user);return user;}

6.@CacheEvict

@CacheEvict 用于标记方法,表示该方法执行时会清除缓存中的数据。

@CacheEvict 在方法执行期间抛出异常不会清空缓存:如果方法执行过程中抛出异常,@CacheEvict 的 allEntries 属性不会生效。

它可以用于删除缓存中的所有键值对,也可以用于清除特定的 key。

  • value 或 cacheNames:指定缓存的名称,可以是单个字符串或字符串数组。
  • key:指定缓存的键,可以使用 SpEL 表达式来定义。
  • condition:指定缓存的条件,只有当条件为 true 时,才会从缓存中获取结果。
  • beforeInvocation:是否在方法执行前清除缓存,为 true 时在方法执行前清除缓存。
  • allEntries:是否清除所有缓存条目,为 true 时清除所有缓存。
    /*** @CacheEvict 在方法执行期间抛出异常不会清空缓存:如果方法执行过程中抛出异常,@CacheEvict 的 allEntries 属性不会生效。* @CacheEvict 用于标记方法,表示该方法执行时会清除缓存中的数据。* 它可以用于删除缓存中的所有键值对,也可以用于清除特定的 key。* value 或 cacheNames:指定要清除的缓存名称。* key:指定要清除的缓存键,可以使用 SpEL 表达式来定义。* allEntries:是否清除所有缓存条目,为 true 时清除所有缓存。* beforeInvocation:是否在方法执行前清除缓存,为 true 时在方法执行前清除缓存。* condition:指定清除缓存的条件,只有当条件为 true 时,才会清除缓存。*/@GetMapping("/delete/{id}")@CacheEvict(key = "#id", allEntries = false)public void deleteUser(@PathVariable Long id) {userService.removeById(id);}

7. @Caching

@Caching 是一个组合注解,可以同时应用多个其他注解,表示该方法会同时执行 @Cacheable、@CachePut 和 @CacheEvict 的操作。

@GetMapping("/save/caching")@Caching(cacheable = @Cacheable( key = "#user.id"),put = @CachePut( key = "#user.id"),evict = @CacheEvict( key = "#user.id"))public User saveUser(User user) {userService.save(user);return user;}

8.@CacheConfig

@CacheConfig 用于在类上设置公共的缓存配置,避免在每个方法上重复配置。

/*** @CacheConfig 用于在类上设置公共的缓存配置,避免在每个方法上重复配置。*/
@RestController
@AllArgsConstructor
@RequestMapping("cache")
@CacheConfig(cacheNames = "user")
public class CacheController {private final IUserService userService;@GetMapping("/query/{id}")@Cacheable(key = "#id",unless = "#result == null")public User getById(@PathVariable Long id){return userService.getById(id);}
}

3.其他属性配置

1.keyGenerator 属性

keyGenerator 属性用于指定默认的键生成器(Key Generator)。如果在方法上未显式指定 key 属性,则使用该属性值作为默认的键生成器。

1.配置生成器

@Configuration
public class CacheConfig {@Bean(name = "customKeyGenerator")public KeyGenerator keyGenerator() {return (target, method, params) -> method.getName() + "[" + Arrays.asList(params) + "]";}
}

等同于

    @Bean(name = "customKeyGenerator")public KeyGenerator keyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object target, Method method, Object... params) {return method.getName() + "[" + Arrays.asList(params) + "]";}};}

2.使用

生成的key为moshangshang_user::getById[[39]]

    @Cacheable(unless = "#result == null",keyGenerator = "customKeyGenerator")public User getById(@PathVariable Long id){return userService.getById(id);}
2. cacheManager 属性

cacheManager 属性用于指定当前使用的 CacheManager 实现类的名称。CacheManager 是 Spring 定义的一个接口,用于管理缓存(Cache)的创建和配置。Spring 提供了多种 CacheManager 的实现,例如 ConcurrentMapCacheManagerEhCacheCacheManagerCaffeineCacheManager 等。通过设置 cacheManager 属性,可以指定使用哪种缓存管理器来管理缓存。

创建自定义的缓存管理器

@Configuration
public class CacheConfig {@Beanpublic ConcurrentMapCacheManager mapCacheManager() {return new ConcurrentMapCacheManager("user-map","user");}}

cacheManager() 方法返回了一个 ConcurrentMapCacheManager 实例,并且指定了缓存名称。这个 CacheManager 将被用于管理名为 指定的缓存。

    /*** 执行的是mapCacheManager的缓存管理器*/@GetMapping("/manger/map/query/{id}")@Cacheable(cacheManager = "mapCacheManager")public User getRedisMangerById(@PathVariable Long id){return userService.getById(id);}
3.cacheResolver 属性

cacheResolver 属性用于指定一个自定义的 CacheResolver 实现。默认情况下,Spring 使用 SimpleCacheResolver 来解析缓存操作。通过自定义 CacheResolver,可以实现更复杂的缓存逻辑,例如根据方法名动态选择缓存名称或缓存管理器。

  • cacheManagercacheResolver 是互斥的:如果同时指定了 cacheManagercacheResolver,Spring 会抛出异常,因为 CacheResolver 的实现会忽略自定义的 CacheManager
  • 自定义 CacheResolver 的灵活性:通过自定义 CacheResolver,可以实现更灵活的缓存管理,例如根据方法名、参数或上下文动态选择缓存名称或缓存管理器 。
  • Spring 4.1 及以上版本:从 Spring 4.1 开始,@Cacheable@CachePut@CacheEvict 等注解的 value 属性不再是强制性的,因为 CacheResolver 可以提供缓存名称信息

自定义缓存解析器

getById方法取user缓存名称下数据,其他取user-map下数据

public class CustomCacheResolver implements CacheResolver {private final ConcurrentMapCacheManager concurrentMapCacheManager;private final RedisCacheManager redisCacheManager;public CustomCacheResolver(ConcurrentMapCacheManager concurrentMapCacheManager, RedisCacheManager redisCacheManager) {this.concurrentMapCacheManager = concurrentMapCacheManager;this.redisCacheManager = redisCacheManager;}@Overridepublic Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {Collection<Cache> caches = new ArrayList<>();if (context.getTarget().getClass() == CacheController.class) {if (context.getMethod().getName().equals("getRedisById")) {caches.add(redisCacheManager.getCache("user"));}else {caches.add(concurrentMapCacheManager.getCache("user-map"));}}return caches;}
}

配置自定义缓存管理器并注册缓存解析器

配置了自定义的CacheManager会导致yml里面的相关配置失效(任何一个都会,比如指定map的缓存管理器,yml配redis,则redis的配置也不生效)

    @Beanpublic ConcurrentMapCacheManager mapCacheManager() {return new ConcurrentMapCacheManager("user-map","user");}@Primary@Beanpublic RedisCacheManager redisCacheManager(RedisTemplate<String, Object> redisTemplate) {return RedisCacheManager.builder(Objects.requireNonNull(redisTemplate.getConnectionFactory())).cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)) // 设置默认缓存过期时间为10分钟.disableCachingNullValues()) // 禁用缓存空值.withInitialCacheConfigurations(initialCacheConfigurations()) // 设置特定缓存的配置.build();}private Map<String, RedisCacheConfiguration> initialCacheConfigurations() {Map<String, RedisCacheConfiguration> initialConfigurations = new HashMap<>();// 设置特定缓存的过期时间initialConfigurations.put("user", RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1)) // 设置特定缓存的过期时间为1小时.disableCachingNullValues());return initialConfigurations;}@Beanpublic CacheResolver customCacheResolver(ConcurrentMapCacheManager concurrentMapCacheManager,RedisCacheManager redisCacheManager) {return new CustomCacheResolver(concurrentMapCacheManager,redisCacheManager);}

测试

  /*** 执行的是RedisCacheManager的缓存管理器*/@GetMapping("/resolver/redis/query/{id}")@Cacheable(unless = "#result == null",cacheResolver = "customCacheResolver")public User getRedisById(@PathVariable Long id){return userService.getById(id);}/*** 执行的是ConcurrentMapCacheManager的缓存管理器*/@GetMapping("/resolver/map/query/{id}")@Cacheable(cacheNames = "user-map",unless = "#result == null",cacheResolver = "customCacheResolver")public User getMapCacheById(@PathVariable Long id){return userService.getById(id);}
4.CacheManagerCustomizer

CacheManagerCustomizer 是一个用于在缓存管理器初始化之前对其进行自定义配置的接口。通过实现该接口的 Bean,可以对缓存管理器进行定制,例如设置缓存名称、是否允许缓存空值、设置缓存过期时间等。

  1. 自定义缓存配置CacheManagerCustomizer 允许在缓存管理器初始化之前对缓存进行配置,例如设置缓存名称、过期时间、序列化方式等。这使得开发者可以针对不同的缓存需求进行灵活配置。
  2. 覆盖默认配置:如果使用了 CacheManagerCustomizer,那么 application.ymlapplication.properties 中的缓存配置将不会生效,因为 CacheManagerCustomizer 会覆盖默认的配置 。
  3. 支持多种缓存类型CacheManagerCustomizer 不仅适用于 ConcurrentMapCacheManager,还可以用于其他类型的缓存管理器,如 RedisCacheManagerCaffeineCacheManager 等。通过实现 CacheManagerCustomizer 接口,可以对不同类型的缓存管理器进行统一的配置 。
  4. 提供回调机制CacheManagerCustomizer 提供了一个 customize 方法,该方法会在缓存管理器初始化之前被调用,允许开发者对缓存管理器进行定制。例如,可以设置缓存名称、允许或禁止缓存空值等 。
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {@Overridepublic void customize(ConcurrentMapCacheManager cacheManager) {cacheManager.setCacheNames(Arrays.asList("user"));cacheManager.setAllowNullValues(false); // 禁用缓存空值}};
}@Beanpublic RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {return (builder) -> {builder.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)) // 默认过期时间为 10 分钟.disableCachingNullValues()); // 禁用缓存空值};}

如果配置了自定义的缓存管理器(redisCacheManager),则CacheManagerCustomizer将不生效

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

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

相关文章

WPF学习笔记(20)Button与控件模板

Button与控件模板一、 Button默认控件模板详解二、自定义按钮模板一、 Button默认控件模板详解 WPF 中的大多数控件都有默认的控件模板。 这些模板定义了控件的默认外观和行为&#xff0c;包括控件的布局、背景、前景、边框、内容等。 官方文档&#xff1a;https://learn.mic…

蓝天居士自传(1)

蓝天居士何许人&#xff1f; 蓝天居士是我的笔名&#xff0c;也可以说是号。就好像李白号青莲居士、欧阳修号六一居士一样。笔者本名彭昊 —— 一个有不少重名重姓者的名字。 笔者小的时候上语文课&#xff0c;无论是小学、初中抑或是高中&#xff0c;都会有鲁迅&#xff08;…

短剧系统开发定制全流程解析:从需求分析到上线的专业指南

一、短剧行业数字化趋势与系统开发必要性在短视频内容爆发式增长的时代背景下&#xff0c;短剧作为一种新兴的内容形式正在迅速崛起。数据显示&#xff0c;2023年中国短剧市场规模已突破300亿元&#xff0c;用户规模达到4.5亿&#xff0c;年增长率超过200%。这一迅猛发展的市场…

getBoundingClientRect() 详解:精准获取元素位置和尺寸

getBoundingClientRect() 是 JavaScript 中一个强大的 DOM API&#xff0c;用于获取元素在视口中的精确位置和尺寸信息。它返回一个 DOMRect 对象&#xff0c;包含元素的坐标、宽度和高度等关键几何信息。 基本用法 const element document.getElementById(myElement); cons…

EXCEL 基础技巧

来源&#xff1a;WPS 官网 初步了解WPS表格-WPS学堂https://www.wps.cn/learning/course/detail/id/635.html 1、格式刷 1.1使用格式刷隔行填充颜色。 首先设置部分表格颜色&#xff0c;选中此区域&#xff0c;双击点击格式刷&#xff0c;然后选中其他表格区域。 这样就可以…

【RK3568 编译rtl8723DU驱动】

RK3568 编译rtl8723DU驱动 编译源码1.解压rtl8723du2.修改Makefile 验证1.加载模块2.开启wifi 在驱动开发中&#xff0c;驱动的编译与集成是实现设备功能的关键环节。本文聚焦于基于 RK3568 处理器平台编译 RTL8723DU WiFi/BT 二合一模块驱动的完整流程&#xff0c;涵盖源码编译…

基于Simulink的二关节机器人独立PD控制仿真

文章目录 理论模型仿真窗口控制函数目标函数仿真 本文是刘金琨. 机器人控制系统的设计与MATLAB仿真的学习笔记。 理论模型 对于二关节机器人系统&#xff0c;其动力学模型为 D ( q ) q C ( q , q ˙ ) q ˙ r D(q)\ddot qC(q,\dot q)\dot q r D(q)q​C(q,q˙​)q˙​r 式…

【技术架构解析】国产化双复旦微FPGA+飞腾D2000核心板架构

本文就一款基于飞腾D2000核心板与两片高性能FPGA的国产化开发主板进行技术解析&#xff0c;包括系统架构、主要硬件模块、关键接口及软件环境&#xff0c;重点阐述各子系统间的数据路径与协同工作方式&#xff0c;旨在为行业内同类产品设计与应用提供参考。 随着国产化要求的加…

Python 数据分析:计算,分组统计1,df.groupby()。听故事学知识点怎么这么容易?

目录1 示例代码2 欢迎纠错3 论文写作/Python 学习智能体1 示例代码 直接上代码。 def grpby1():xls "book.xls"df pd.DataFrame(pd.read_excel(xls, engine"xlrd"))print(df)"""序号 分类 销量0 1 文学 51 2 计算机…

【解决“此扩展可能损坏”】Edge浏览器(chrome系列通杀))扩展损坏?一招保留数据快速修复

引言 如果你想保留你的数据&#xff0c;敲重点&#xff1a;不要点击修复&#xff0c;不要修复&#xff0c;不要修复 在使用 Microsoft Edge 浏览器时&#xff0c;您可能会遇到扩展程序显示“此扩展程序可能已损坏”的提示&#xff0c;且启用按钮无法点击。这一问题让许多用户感…

AI专业化应用加速落地,安全治理挑战同步凸显

7月2日&#xff0c;2025全球数字经济大会在北京国家会议中心开幕。本届大会以“建设数字友好城市”为主题&#xff0c;聚焦数字技术对城市发展的影响。开幕式上&#xff0c;一首完全由AI生成的MV成为焦点——从歌词、谱曲、演唱到视频制作全流程AI生成&#xff0c;展现人工智能…

Python统一调用多家大模型API指南

随着大模型技术的快速发展&#xff0c;市场上出现了越来越多的LLM服务提供商&#xff0c;包括OpenAI、Anthropic、Google、百度、阿里云等。作为开发者&#xff0c;我们经常需要在不同的模型之间切换&#xff0c;或者同时使用多个模型来满足不同的业务需求。本文将详细介绍如何…

【ESP32】1.编译、烧录、创建工程

标题打开一个Hello world工程并烧录 点击环境搭建链接 遇到的问题&#xff1a; 1.ESP32在VSCODE中烧录代码时&#xff0c;跳出窗口&#xff0c;OPenOCD is not running ,do you want to launch it? 可能是OCD没安装&#xff0c;重新安装 ESP-IDF试一下&#xff0c;在终端命令窗…

调参——optuna

它基于贝叶斯优化&#xff08;Bayesian Optimization&#xff09;思想&#xff0c;通过构建一个概率模型来预测超参数组合的性能&#xff0c;从而高效地探索超参数空间。相比传统网格搜索&#xff08;Grid Search&#xff09;或随机搜索&#xff08;Random Search&#xff09;&…

Redis的缓存击穿和缓存雪崩

Redis缓存击穿和缓存雪崩是两种常见的缓存问题&#xff0c;它们都可能导致系统性能下降甚至崩溃。以下是对它们的详细解释&#xff1a;一、缓存击穿定义缓存击穿是指一个特定的缓存数据失效&#xff08;例如过期&#xff09;&#xff0c;而此时大量请求同时访问这个数据&#x…

Python训练营Day4

浙大疏锦行 Python训练营Day4 内容&#xff0c;pandas处理表格信息&#xff1a; 查看表格统计信息&#xff1a; data.mean()data.mode()data.median() 查看表格信息&#xff1a; data.info()data.describe()data.isnull()data.head() 填充空缺列&#xff1a; 数值型&#xff…

React 基本介绍与项目创建

为什么使用 React 以及前端框架 工作原理 React 通过构建虚拟 DOM&#xff08;Virtual DOM&#xff09;来高效管理界面。当组件的状态或属性发生变化时&#xff0c;React 会重新渲染生成新的虚拟 DOM&#xff0c;并通过 Diff 算法找出新旧虚拟 DOM 树之间的差异&#xff0c;最…

OpenCV CUDA模块设备层-----“小于阈值设为零” 的图像处理函数thresh_to_zero_func()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 OpenCV CUDA 模块&#xff08;cudev&#xff09; 中的一个仿函数生成器&#xff0c;用于创建一个 “小于阈值设为零” 的图像处理函数对象。 这个函…

数字图像处理学习笔记

1-图像处理基础_哔哩哔哩_bilibili 输出图像像素点需要将图象值要作类型转换&#xff0c;转成Int 图像仿射变换 线性变换平移 线性变换&#xff1a; 1&#xff0c;变换前直线&#xff0c;变换后仍然直线 2&#xff0c;直线比例不变 3&#xff0c;直线到远点的距离不变 仿射变…

用systemd管理GreatSQL服务详解

用systemd管理GreatSQL服务详解 1.GreatSQL服务文件 官网 greatsql.service 文件 [Unit] DescriptionGreatSQL Server Documentationman:mysqld(8) Documentationhttp://dev.mysql.com/doc/refman/en/using-systemd.html Afternetwork.target Aftersyslog.target [Install] …