SpringBoot-Cache-Redis

本文深入解析SpringBoot中缓存的实现原理,包括@Cacheable、@CachePut、@CacheEvict等注解的使用,以及如何整合Redis进行高效的数据缓存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot缓存

spring定义了CacheCacheManager两个接口来统一管理不同的缓存技术,同时也支持使用JCache(JSR-107)注解来简化我们开发

  • Cache:缓存接口,定义缓存操作,实现有:RedisCache,EhCacheCache,ConcurrentMapCache等
  • CacheManager:缓存管理器,管理各种缓存(Cache)组件
几个常见的注解
缓存注解解释
@Cacheable主要配置在方法上,根据方法的请求参数对其结果进行缓存
@CacheEvict清空缓存
@CachePut方法被调用的同时,将结果缓存
@EnableCaching开启基于注解的缓存
SpringBoot缓存的运行原理

缓存的自动配置类CacheAutoConfiguration导入了CacheConfigurationImportSelector
在这里插入图片描述
其为我们导入了十个缓存配置类
在这里插入图片描述
默认生效的是SimpleCacheConfiguration
在这里插入图片描述
其给容器中注册了一个CacheManager:ConcurrentMapCacheManager
获取和创建ConcurrentMapCacheManager类型的缓存组件,将数据保存在ConcurrentMap
在这里插入图片描述

运行流程:

1.方法运行之前,先去查询cache缓存组件,按照cacheName指定的名字获取,第一次获取缓存如果没有cache组件会自动创建出来

   public Cache getCache(String name) {
   	Cache cache = this.cacheMap.get(name);
   	if (cache == null && this.dynamic) {
   		synchronized (this.cacheMap) {
   			cache = this.cacheMap.get(name);
   			if (cache == null) {
   				cache = createConcurrentMapCache(name);
   				this.cacheMap.put(name, cache);
   			}
   		}
   	}
   	return cache;
   }

2.去cache中按照key查找缓存的内容,key默认就是方法的参数

   protected Object lookup(Object key) {
   	return this.store.get(key);
   }

3.没有查找到缓存就调用目标方法,也就是去查找数据库
4.将找到的结果放进缓存中

public void put(Object key, @Nullable Object value) {
		this.store.put(key, toStoreValue(value));
	}

@Cacheable注解总的来说就是其标注的方法执行之前先来检查缓存中有没有数据,没有就去数据库中查并将结果放进缓存

缓存实例

1.开启基于注解的缓存

@SpringBootApplication
@EnableCaching//开启基于注解的缓存
@MapperScan(value = "com.lb.springboot.mapper")
public class SpringbootCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootCacheApplication.class, args);
    }

}

2.在方法上标注@Cacheable并设置缓存名

@Service
public class EmployeeService {

    @Autowired
    EmployeeMapper employeeMapper;

    @Cacheable(value = "getEmp")
    public Employee getEmp(int id){
        System.out.println("查询用户ID:"+id);
        return employeeMapper.getEmp(id);
    }
}

3.效果展示
@Cacheable
第一次获取员工信息时,因为没有缓存在没有该信息,所以会执行方法去数据库查找,并将结果放进缓存中
在这里插入图片描述
第二次获取时,因为缓存已经有该信息,所以就不需要执行方法去数据库查找而是直接从缓存中获取
在这里插入图片描述
@CachePut

在方法上标注@CachePut并设置缓存名

    @CachePut(value = "emp",key = "#result.id")
    public Employee updateEmp(Employee employee){
        System.out.println("更新用户ID:"+employee.getId());
        employeeMapper.updateEmp(employee);
        return employee;
    }

效果
每次调用方法都会执行
在这里插入图片描述
并且将更新后的数据保存在缓存中
在这里插入图片描述
CacheEvict

在方法上标注@CacheEvict并设置要删除的key

    @CacheEvict(value = "emp",key = "#id")
    public void deleteEmp(int id){
        System.out.println("deleteEmp: "+id);
    }

效果
会把缓存中对应的key删除
在这里插入图片描述
随后获取数据时,因为缓存中该数据被删除了,所以需要重新调用方法去数据库查询
在这里插入图片描述

springboot整合redis

导入redis依赖

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

启动redis服务和连接redis
在这里插入图片描述

在这里插入图片描述
springboot中redis操作主要有两大类

  • RedisTemplate<Object,Object>
  • StringRedisTemplate<String,String>

StringRedisTemplate继承RedisTemplate

redis支持String,Hash,Set,List,Zset五大类型,这里只测试List和String,其他类型的方法都是大同小异

public class SpringbootRedisApplicationTests {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Test
    public void contextLoads() {
        stringRedisTemplate.opsForValue().set("msg","redis" );
        System.out.println(stringRedisTemplate.opsForValue().get("msg"));

在这里插入图片描述

public class SpringbootRedisApplicationTests {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Test
    public void contextLoads() {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        stringRedisTemplate.opsForList().leftPushAll("list",list );
        System.out.println(stringRedisTemplate.opsForList().index("list",2 ));
    }

在这里插入图片描述
在请求中使用redis

@RestController
public class cacheController {
    @Autowired
    EmployeeService employeeService;

    @GetMapping("/getEmp/{id}")
    public Employee get(@PathVariable("id") int id){
        Employee employee = employeeService.getEmp(id);
        return employee;
    }
}

注意把对象存进redis中时需要序列化
在这里插入图片描述
请求

@RestController
public class cacheController {
    @Autowired
    EmployeeService employeeService;

    @GetMapping("/getEmp/{id}")
    public Employee get(@PathVariable("id") int id){
        Employee employee = employeeService.getEmp(id);
        return employee;
    }
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

完整代码在我的GitHub

### Spring Boot 中 Redis 和 CTG-Cache 的集成教程 在 Spring Boot 项目中同时集成 Redis 和 CTG-Cache 可以为应用程序提供高效的缓存管理和性能优化功能。以下是实现这一目标的关键步骤和技术细节。 #### 1. 添加依赖项 要集成 Redis 和 CTG-Cache,需在项目的 `pom.xml` 文件中添加必要的 Maven 依赖项: ```xml <dependencies> <!-- Spring Data Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- Jedis Client (or Lettuce as an alternative) --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <!-- CTG Cache Library --> <dependency> <groupId>com.ctg.cache</groupId> <artifactId>ctg-cache-core</artifactId> <version>{latest-version}</version> </dependency> </dependencies> ``` 上述配置中的 `spring-boot-starter-data-redis` 是用于支持 Redis 缓存的核心库[^2],而 `jedis` 或其他客户端则提供了与 Redis 进行通信的能力。对于 CTG-Cache,应根据官方文档指定最新版本号。 --- #### 2. 配置 Redis 通过创建一个名为 `application.properties` 或 `application.yml` 的文件来定义 Redis 的连接参数: ##### application.properties 示例: ```properties # Redis Configuration spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.database=0 spring.redis.timeout=6000ms ``` 这些属性允许开发者轻松调整 Redis 实例的位置、端口以及超时设置等重要选项。 --- #### 3. 自定义 CTG-Cache 配置类 为了使 CTG-Cache 能够无缝工作,可以编写自定义的 Java 配置类以初始化其上下文环境: ```java import com.ctg.cache.core.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class CtgCacheConfig { @Bean public CacheManager cacheManager() { // 初始化并返回 CTG Cache Manager 对象 return new CacheManager(); } } ``` 此代码片段展示了如何利用 Spring 的 Bean 容器机制加载 CTG-Cache 组件实例[^3]。 --- #### 4. 使用双重缓存策略 当需要结合两种不同的缓存技术时,推荐采用分层架构设计模式。例如,在内存级操作优先考虑 Redis,而对于更持久化的存储需求可转向 CTG-Cache。 下面是一个简单的服务方法示例,演示了双缓存逻辑的应用场景: ```java @Service public class DualCacheService { private final StringRedisTemplate redisTemplate; // Redis Template for operations private final CacheManager ctgCacheManager; // CTG Cache Manager instance public DualCacheService(StringRedisTemplate redisTemplate, CacheManager ctgCacheManager) { this.redisTemplate = redisTemplate; this.ctgCacheManager = ctgCacheManager; } public Object getDataFromCaches(String key) { // Step A: Try fetching data from Redis first. ValueOperations<String, String> ops = redisTemplate.opsForValue(); String valueInRedis = ops.get(key); if (valueInRedis != null && !valueInRedis.isEmpty()) { System.out.println("Data found in Redis."); return valueInRedis; } else { System.out.println("No data in Redis, checking CTG Cache..."); // Step B: If not present in Redis, try retrieving it via CTG Cache. Object cachedObject = ctgCacheManager.get(key); if (cachedObject != null) { System.out.println("Data retrieved successfully from CTG Cache."); // Optional step to sync back into Redis for future requests. redisTemplate.opsForValue().set(key, cachedObject.toString()); return cachedObject; } } return null; // No matching entry was located across both caches. } } ``` 该例子说明了如何先查询 Redis 并在其未命中后再尝试访问 CTG-Cache[^1]。 --- #### 5. 测试与验证 完成以上开发后,务必执行单元测试和集成测试以确认整个流程正常运作无误。可以通过模拟不同条件下的请求路径覆盖所有可能的情况。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lpepsi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值