Spring Cache
Spring Cache可以通过注解的形式实现对方法的缓存管理。
使用场景:一个方法在调用时,先从缓存获取数据,缓存有数据直接返回,缓存无数据查询数据库再返回数据,同时存储到缓存。
核心注解
@Cacheable
:表示一个方法的返回结果会被放入缓存。在调用这个方法时,先获取缓存,如果缓存中有数据直接返回,不执行该方法;如果缓存中无数据,则执行该方法。@CachePut
:表示一个方法的返回结果会更新缓存。@CacheEvict
:表示一个方法执行后会删除缓存。@Caching
:组合多个缓存操作。@CacheConfig
:类级别共享缓存配置(如缓存名称)。@Caching
允许在同一方法上使用多个嵌套的@Cacheable
、@CachePut
和@CacheEvict
注释。
POM依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- 使用 Redis 作为缓存实现 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
启用缓存
java
@SpringBootApplication
@EnableCaching // 开启缓存支持
public class Application { ... }
添加配置
yml
server:
port: 8084
spring:
application:
name: springboot-cache
datasource:
url: jdbc:mysql://localhost:3306/user_db_test
username: root
password: admin123
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
redis:
# Redis服务器地址
host: localhost
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password: 123456
# Redis数据库索引(默认为0)
database: 0
# 连接超时时间(毫秒)
timeout : 300
client-type: lettuce #切换jedis客户端,改成jedis
lettuce: #切换jedis客户端,改成jedis
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 8
# 连接池中的最小空闲连接
min-idle: 0
cache:
# spring cache使用redis缓存
# redis # 分布式场景(推荐)
# caffeine # 本地高性能缓存(单机)
# ehcache # 本地复杂缓存
# simple # 基于 ConcurrentHashMap 的默认实现(测试用)
type: redis
redis:
# 是否缓存空值,防止缓存穿透
cache-null-values: true
# 缓存过期时间(单位为毫秒)
time-to-live: 100000
# 缓存前缀,用于区分其他缓存,不指定前缀,默认使用缓存的名字作为前缀
# key-prefix: CACHE_
# 是否使用缓存前缀,false不使用任何缓存前缀
# use-key-prefix: false
使用
java
// 查询时缓存结果(key = "product::" + 参数id)
@Cacheable(value = "product", key = "#id")
public Product getProductById(Long id) {
return productRepository.findById(id).orElse(null);
}
// 更新数据时清除旧缓存
@CacheEvict(value = "product", key = "#product.id")
public void updateProduct(Product product) {
productRepository.save(product);
}
// 组合操作:更新数据 + 清理列表缓存
@Caching(
put = @CachePut(value = "product", key = "#product.id"),
evict = @CacheEvict(value = "productList", allEntries = true)
)
public Product saveProduct(Product product) {
return productRepository.save(product);
}
// 缓存用户推荐结果(Key: rec::用户ID::版本)
@Cacheable(value = "userRecs", key = "#userId + '::' + #version")
public List<Recommendation> getRecommendations(Long userId, String version) {
return recommendationEngine.calculate(userId); // 复杂计算
}
自定义key
java
@Cacheable(value="users", key="#user.id") // 使用参数对象的属性
@Cacheable(value="items", key="T(String).format('ITEM:%s', #id)") // 格式化Key
条件缓存
java
// 仅当 id > 10 时缓存
@Cacheable(value="product", key="#id", condition="#id > 10")
// 结果不为 null 时缓存
@Cacheable(value="product", unless="#result == null")