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. 监控缓存命中率:定期检查缓存效果
相关推荐
武子康2 小时前
Java-208 RabbitMQ Topic 主题交换器详解:routingKey/bindingKey 通配符与 Java 示例
java·分布式·性能优化·消息队列·系统架构·rabbitmq·java-rabbitmq
后端小张3 小时前
【JAVA 进阶】SpringMVC全面解析:从入门到实战的核心知识点梳理
java·开发语言·spring boot·spring·spring cloud·java-ee·springmvc
Lucky小小吴4 小时前
ClamAV扫描速度提升6.5倍:服务器杀毒配置优化实战指南
java·服务器·网络·clamav
handsome_sai9 小时前
【Java 线程池】记录
java
大学生资源网10 小时前
基于springboot的唐史文化管理系统的设计与实现源码(java毕业设计源码+文档)
java·spring boot·课程设计
guslegend10 小时前
SpringSecurity源码剖析
java
roman_日积跬步-终至千里11 小时前
【人工智能导论】02-搜索-高级搜索策略探索篇:从约束满足到博弈搜索
java·前端·人工智能
大学生资源网11 小时前
java毕业设计之儿童福利院管理系统的设计与实现(源码+)
java·开发语言·spring boot·mysql·毕业设计·源码·课程设计
JasmineWr11 小时前
JVM栈空间的使用和优化
java·开发语言