SpringBoot--Spring Boot原生缓存基于Redis的Cacheable注解使用

SpringBoot--Spring Boot原生缓存基于Redis的Cacheable注解使用

文章目录

  • [SpringBoot--Spring Boot原生缓存基于Redis的Cacheable注解使用](#SpringBoot--Spring Boot原生缓存基于Redis的Cacheable注解使用)
    • 概述
    • [1. 基础配置](#1. 基础配置)
      • [1.1 添加依赖](#1.1 添加依赖)
      • [1.2 配置文件](#1.2 配置文件)
      • [1.3 序列化配置](#1.3 序列化配置)
    • [2. 缓存注解使用](#2. 缓存注解使用)
      • [2.1 @Cacheable - 缓存查询](#2.1 @Cacheable - 缓存查询)
      • [2.2 @CacheEvict - 缓存清除](#2.2 @CacheEvict - 缓存清除)
    • [3. 自定义TTL管理](#3. 自定义TTL管理)
      • [3.1 自定义缓存管理器](#3.1 自定义缓存管理器)
      • [3.2 缓存配置类](#3.2 缓存配置类)
      • [3.3 不同TTL的缓存使用](#3.3 不同TTL的缓存使用)
    • [4. 关键注意事项](#4. 关键注意事项)
      • [4.1 配置冲突解决](#4.1 配置冲突解决)
      • [4.2 缓存键生成规则](#4.2 缓存键生成规则)
      • [4.3 TTL优先级](#4.3 TTL优先级)
      • [4.4 空值缓存策略](#4.4 空值缓存策略)
      • [4.5 最佳实践](#4.5 最佳实践)

概述

Spring Boot 通过 @Cacheable@CacheEvict 注解简化了 Redis 缓存的使用,提供了声明式的缓存管理方案。

1. 基础配置

1.1 添加依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

1.2 配置文件

yml 复制代码
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    database: 1
  cache:
    type: redis
    redis:
      cache-null-values: false   # 不缓存null值
      time-to-live: 9000ms      # 默认过期时间
      use-key-prefix: true      # 使用key前缀

1.3 序列化配置

java 复制代码
@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // 使用Jackson序列化
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), 
                                   ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        
        return template;
    }
}

2. 缓存注解使用

2.1 @Cacheable - 缓存查询

  • 参数说明

    • value ="bills":缓存名称,在 Redis 中作为前缀

    • key ="#id":缓存键,使用方法的 id 参数

java 复制代码
@Service
public class BillService {
    
    /**
     * 查询账单并缓存结果
     * value: 缓存名称(Redis中的前缀)
     * key: 缓存键,使用SpEL表达式
     */
    @Cacheable(value = "bills", key = "#id")
    public ResultJSON findBillById(Integer id) {
        // 只有缓存不存在时才会执行此方法
        return ResultJSON.ok(this.getById(id));
    }
}
  • 工作机制:
  1. 检查缓存中是否存在键为 bills::[id] 的数据
  2. 存在:直接返回缓存数据,不执行方法
  3. 不存在:执行方法,将结果存入缓存

2.2 @CacheEvict - 缓存清除

  • 参数说明

    • value ="bills":缓存名称,与 @Cacheable 中的一致

    • key ="#id":缓存键,使用方法的 id 参数

java 复制代码
@CacheEvict(value = "bills", key = "#id")
public ResultJSON deleteBill(Integer id) {
    // 方法执行成功后,自动删除对应的缓存
    return ResultJSON.ok(this.removeById(id));
}
清除所有缓存
java 复制代码
@CacheEvict(value = "bills", allEntries = true)
public ResultJSON clearAllBills() {
    // 清除bills缓存区域的所有数据
    return ResultJSON.ok("所有账单缓存已清除");
}

3. 自定义TTL管理

3.1 自定义缓存管理器

java 复制代码
public class MyRedisCacheManager extends RedisCacheManager {
    
    public MyRedisCacheManager(RedisCacheWriter cacheWriter, 
                              RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
    }
    
    @Override
    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
        // 解析缓存名称中的TTL配置,格式:cacheName#ttlSeconds
        String[] array = StringUtils.delimitedListToStringArray(name, "#");
        name = array[0];
        
        if (array.length > 1) {
            long ttl = Long.parseLong(array[1]);
            cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
        }
        
        return super.createRedisCache(name, cacheConfig);
    }
}

3.2 缓存配置类

java 复制代码
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
    
    @Value("${spring.redis.host}")
    private String hostName;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.port}")
    private Integer port;
    @Value("${spring.redis.database}")
    private int database;
    
    @Bean
    public CacheManager cacheManager() {
        // 默认缓存配置(1天过期)
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration
            .defaultCacheConfig()
            .entryTtl(Duration.ofDays(1))
            .computePrefixWith(cacheName -> "caching:" + cacheName);
        
        return new MyRedisCacheManager(
            RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory()),
            defaultCacheConfig
        );
    }
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(hostName);
        config.setPort(port);
        config.setDatabase(database);
        config.setPassword(RedisPassword.of(password));
        //        configuration.setHostName("127.0.0.1");
        //        configuration.setPort(6379);
        //        configuration.setDatabase(0);
        //        configuration.setPassword("123456"); // 密码
        
        return new LettuceConnectionFactory(config);
    }
}

3.3 不同TTL的缓存使用

java 复制代码
@Service
public class BillService {
    
    // 3600秒过期
    @Cacheable(cacheNames = "billCache#3600", key = "#id")
    public ResultJSON findBillById(Integer id) {
        return ResultJSON.ok(this.getById(id));
    }
    
    // 4800秒过期  
    @Cacheable(cacheNames = "providerCache#4800", key = "#id")
    public ResultJSON getProviderById(Integer id) {
        return ResultJSON.ok(this.getById(id));
    }
    
    // 清除指定缓存(需要匹配TTL配置)
    @CacheEvict(cacheNames = "billCache#3600", key = "#id")
    public ResultJSON deleteBill(Integer id) {
        return ResultJSON.ok(this.removeById(id));
    }
}

4. 关键注意事项

4.1 配置冲突解决

  • 问题RedisTemplateCacheConfig 配置可能冲突
  • 建议 :在大多数场景下,使用 CacheConfig 统一管理缓存配置

4.2 缓存键生成规则

  • 默认格式caching::cacheName::key
  • 示例caching:billCache::1

4.3 TTL优先级

  1. 最高 :注解中通过 # 指定的TTL(如 billCache#3600
  2. 中等:YAML中针对具体cacheName的配置
  3. 最低:全局默认TTL配置

4.4 空值缓存策略

yml 复制代码
spring:
  cache:
    redis:
      cache-null-values: false  # 推荐设置为false,避免缓存空值

4.5 最佳实践

  1. 合理设置TTL:根据数据更新频率设置不同的过期时间
  2. 避免缓存雪崩:为不同缓存设置不同的TTL
  3. 及时清理缓存:数据更新后立即清除相关缓存
  4. 监控缓存命中率:定期检查缓存效果
相关推荐
想摆烂的不会研究的研究生1 小时前
每日八股——Redis(1)
数据库·经验分享·redis·后端·缓存
毕设源码-郭学长1 小时前
【开题答辩全过程】以 基于SpringBoot技术的美妆销售系统为例,包含答辩的问题和答案
java·spring boot·后端
梨落秋霜2 小时前
Python入门篇【文件处理】
android·java·python
N***H4862 小时前
springcloud springboot nacos版本对应
spring boot·spring·spring cloud
Java 码农2 小时前
RabbitMQ集群部署方案及配置指南03
java·python·rabbitmq
哈库纳玛塔塔2 小时前
放弃 MyBatis,拥抱新一代 Java 数据访问库
java·开发语言·数据库·mybatis·orm·dbvisitor
S***q3773 小时前
Spring Boot管理用户数据
java·spring boot·后端
BD_Marathon3 小时前
SpringBoot——辅助功能之切换web服务器
服务器·前端·spring boot
天“码”行空3 小时前
java面向对象的三大特性之一多态
java·开发语言·jvm
毕设源码-郭学长3 小时前
【开题答辩全过程】以 基于SpringBoot框架的民俗文化交流与交易平台的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端