当前位置: 首页 > news >正文

Spring Boot 3 整合 Spring Cache 与 Redis 缓存实战

🚀 作者主页: 有来技术
🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot
🌺 仓库主页: Gitee 💫 Github 💫 GitCode
💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正!

目录

  • 什么是 Spring Cache?
  • Spring Cache 常用 API
    • @Cacheable
    • @CacheEvict
    • @CachePut
    • @Caching
  • Spring Boot 整合 Spring Cache (Redis 缓存)
    • 项目依赖 pom.xml
    • 项目配置 application.yml
    • 自动装配配置类 RedisCacheConfig
  • Spring Boot 路由缓存实战
    • 获取路由数据缓存
    • 更新路由缓存失效
  • Spring Cache 问题整理
    • @Cacheable 缓存的 key 双冒号
  • 结语
  • 开源项目

什么是 Spring Cache?

Spring Cache是Spring框架提供的一层缓存抽象,旨在简化应用程序中的缓存管理。通过使用Spring Cache,开发者能够在方法级别方便地定义缓存策略,提高应用性能、响应速度,并减轻底层数据源的负载。该框架提供一系列注解,如@Cacheable@CacheEvict@CachePut,以及对多种底层缓存实现的支持,如EhCache、Redis等。它为应用程序提供了一种统一、方便、灵活的缓存管理方式,允许开发者通过简单的配置实现复杂的缓存逻辑,同时与Spring框架紧密集成。这种抽象层的存在使得在更改底层缓存框架时更为轻松,同时提供了一致的配置接口和更强大的高级特性。

Spring Cache 常用 API

@Cacheable

@Cacheable 用于标记一个方法的结果应该被缓存。当在该方法被调用时,Spring首先检查缓存中是否已经有了预期的结果,如果有,直接返回缓存中的结果而不执行实际的方法体。

javaCopy code@Cacheable(cacheNames = "exampleCache", key = "'exampleKey'")
public String getCachedData() {// 执行实际的方法体,结果会被缓存
}

@CacheEvict

@CacheEvict 用于标记一个方法在执行后清空缓存。可以指定清空的缓存名称和清空的条件。

javaCopy code@CacheEvict(cacheNames = "exampleCache", key = "'exampleKey'")
public void clearCache() {// 执行实际的方法体,之后清空缓存
}

@CachePut

@CachePut 用于标记一个方法的结果应该被放入缓存,常用于在方法执行后更新缓存。

javaCopy code@CachePut(cacheNames = "exampleCache", key = "'exampleKey'")
public String updateCache() {// 执行实际的方法体,结果会被放入缓存
}

@Caching

@Caching 允许同时应用多个缓存操作注解。

javaCopy code@Caching(evict = {@CacheEvict(cacheNames = "cache1", key = "'key1'"),@CacheEvict(cacheNames = "cache2", key = "'key2'")}
)
public void clearMultipleCaches() {// 执行实际的方法体,清空多个缓存
}

Spring Boot 整合 Spring Cache (Redis 缓存)

完整项目源码:youlai-boot

项目依赖 pom.xml

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

项目配置 application.yml

spring:data:redis:database: 6host: localhostport: 6379password: 123456timeout: 10slettuce:pool:# 连接池最大连接数 默认8 ,负数表示没有限制max-active: 8# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认-1max-wait: -1# 连接池中的最大空闲连接 默认8max-idle: 8# 连接池中的最小空闲连接 默认0min-idle: 0cache:# 缓存类型 redis、none(不使用缓存)type: redis# 缓存时间(单位:ms)redis:time-to-live: 3600000# 缓存null值,防止缓存穿透cache-null-values: true

自动装配配置类 RedisCacheConfig

package com.youlai.system.config;import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;/*** Redis 缓存配置** @author haoxr* @since 2023/12/4*/
@EnableCaching
@EnableConfigurationProperties(CacheProperties.class)
@Configuration
public class RedisCacheConfig {/*** 自定义 RedisCacheManager* <p>* 修改 Redis 序列化方式,默认 JdkSerializationRedisSerializer** @param redisConnectionFactory {@link RedisConnectionFactory}* @param cacheProperties        {@link CacheProperties}* @return {@link RedisCacheManager}*/@Beanpublic RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory, CacheProperties cacheProperties){return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(redisCacheConfiguration(cacheProperties)).build();}/*** 自定义 RedisCacheConfiguration** @param cacheProperties {@link CacheProperties}* @return {@link RedisCacheConfiguration}*/@BeanRedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()));config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));CacheProperties.Redis redisProperties = cacheProperties.getRedis();if (redisProperties.getTimeToLive() != null) {config = config.entryTtl(redisProperties.getTimeToLive());}if (!redisProperties.isCacheNullValues()) {config = config.disableCachingNullValues();}if (!redisProperties.isUseKeyPrefix()) {config = config.disableKeyPrefix();}config = config.computePrefixWith(name -> name + ":");// 覆盖默认key双冒号  CacheKeyPrefix#prefixedreturn config;}}

Spring Boot 路由缓存实战

完整项目源码:youlai-boot

获取路由数据缓存

获取路由列表,通过 @Cacheable 注解,将方法返回的路由列表数据缓存至 Redis。当再次请求时,不再进入方法体,而是直接从 Redis 中读取缓存数据并返回,以提高性能。

    /*** 获取路由列表*/@Override@Cacheable(cacheNames = "menu", key = "'routes'") // cacheNames 为必填项,key 需要使用引号,否则会被识别为变量。public List<RouteVO> listRoutes() {List<RouteBO> menuList = this.baseMapper.listRoutes();return buildRoutes(SystemConstants.ROOT_NODE_ID, menuList);}

更新路由缓存失效

若需要在路由信息更新时使缓存失效,可以使用 @CacheEvict 注解,它用于在方法执行之后(默认)从缓存中移除条目。

    /*** 新增/修改菜单*/@Override@CacheEvict(cacheNames = "menu", key = "'routes'",beforeInvocation = true)public boolean saveMenu(MenuForm menuForm) {String path = menuForm.getPath();MenuTypeEnum menuType = menuForm.getType();// 如果是目录if (menuType == MenuTypeEnum.CATALOG) {if (menuForm.getParentId() == 0 && !path.startsWith("/")) {menuForm.setPath("/" + path); // 一级目录需以 / 开头}menuForm.setComponent("Layout");}// 如果是外链else if (menuType == MenuTypeEnum.EXTLINK) {menuForm.setComponent(null);}SysMenu entity = menuConverter.form2Entity(menuForm);String treePath = generateMenuTreePath(menuForm.getParentId());entity.setTreePath(treePath);return this.saveOrUpdate(entity);}

更新菜单后,Redis 中缓存的路由数据将被清除。再次获取路由时,才会将新的路由数据缓存到 Redis 中。

Spring Cache 问题整理

@Cacheable 缓存的 key 双冒号

默认情况下 @Cacheable 使用双冒号 :: 拼接 cacheNameskey

@Cacheable(cacheNames = "menu", key = "'routes'") 

参考源码 RedisCacheConfiguration#prefixCacheNameWith

如果需要将双冒号改成单个冒号,需要重写 RedisCacheConfiguration#computePrefixWith 方法

config = config.computePrefixWith(name -> name + ":");//覆盖默认key双冒号  CacheKeyPrefix#prefixed

结语

Spring Cache 为 Spring 应用程序提供了简便的缓存管理抽象,通过注解如 @Cacheable@CacheEvict@CachePut,开发者能方便定义缓存策略。整合Spring Boot 与 Redis 缓存实例展示了如何配置、使用Spring Cache,提升应用性能。通过实战演示菜单路由缓存,突显 @Cacheable@CacheEvict 的实际应用,以及解决 @Cacheable 默认key双冒号的问题。

开源项目

  • SpringCloud + Vue3 微服务商城
GithubGitee
后端youlai-mall 🍃youlai-mall 🍃
前端mall-admin🌺mall-admin 🌺
移动端mall-app 🍌mall-app 🍌
  • SpringBoot 3+ Vue3 单体权限管理系统
GithubGitee
后端youlai-boot 🍃youlai-boot 🍃
前端vue3-element-admin 🌺vue3-element-admin 🌺
http://www.lryc.cn/news/255154.html

相关文章:

  • kubeadm 安装k8s1.28.x 底层走containerd 容器
  • “分割“安卓用户,对标iOS,鸿蒙崛起~
  • 【Vulnhub 靶场】【hacksudo: ProximaCentauri】【简单 - 中等】【20210608】
  • share pool的组成
  • 应用案例 | 基于三维视觉的汽车零件自动化拧紧解决方案
  • Redis server启动源码
  • C++基础 强制转换
  • 【python、opencv】opencv仿射变换原理及代码实现
  • mac本地部署stable-diffusion
  • dockers安装rabbitmq
  • 07、pytest指定要运行哪些用例
  • springboot集成cxf
  • 快速认识什么是:Kubernetes
  • YOLOv6 学习笔记
  • paypal贝宝怎么绑卡支付
  • 活动回顾|德州仪器嵌入式技术创新发展研讨会(上海站)成功举办,信驰达科技携手TI推动技术创新
  • Vue 循环走马灯
  • <Linux>(极简关键、省时省力)《Linux操作系统原理分析之Linux文件管理(3)》(27)
  • 【华为数据之道学习笔记】3-2 基础数据治理
  • GO设计模式——7、适配器模式(结构型)
  • Java实现TCP一对一通信,实现UDP群聊通信
  • Vue + Element 实现按钮指定间隔时间点击
  • UE Websocket笔记
  • STM32h7 接收各种can id情况下滤波器的配置
  • 《深入理解计算机系统》学习笔记 - 第三课 - 浮点数
  • 总结:服务器批量处理http请求的大致流程
  • 算法通关村第十八关-青铜挑战回溯是怎么回事
  • 区分node,npm,nvm
  • 7-2 小霸王
  • Linux内核上游提交完整流程及示例