Spring Boot 中使用缓存(Cache)
缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取。在 Spring Boot 中,使用缓存非常简单,主要依赖于 Spring Cache 提供的注解支持。本文将介绍如何在 Spring Boot 中使用缓存,并详细解释常用的三个注解:@Cacheable
、@CachePut
和 @CacheEvict
。
1. 添加 Maven 依赖
使用 Redis 作为缓存提供者,在 Spring 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>
2. 在配置文件中加入相关配置
使用默认 lettuce
作为客户端,配置如下:
spring:
redis:
host: x.x.x.x
port: 6379
password: # Redis 服务器密码。
database: 0 # Redis 数据库号,默认为 0。
timeout: 1000 # Redis 连接超时时间,单位:毫秒。
lettuce:
pool:
max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。
max-idle: 8 # 默认连接数最小空闲的连接数,默认为 8 。使用负数表示没有限制。
min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。
max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。
cache:
type: redis
redis:
key-prefix: demo
time-to-live: 6000
3. 创建 Redis 配置类
@EnableCaching // 启用 Spring Boot 的缓存功能
@Configuration
public class CacheConfig {
private static final String COLON = ":";
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
// 创建默认的 RedisCacheConfiguration
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 获取 Redis 相关的配置属性
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
// 配置缓存键的前缀
config = config.computePrefixWith(cacheName -> {
String keyPrefix = redisProperties.getKeyPrefix();
if (StringUtils.hasText(keyPrefix)) {
// 确保前缀以 COLON 结尾
keyPrefix = keyPrefix.lastIndexOf(COLON) == -1 ? keyPrefix + COLON : keyPrefix;
return keyPrefix + cacheName + COLON; // 生成带前缀的缓存键
}
return cacheName + COLON; // 无前缀时,直接使用缓存名称
});
// 设置键的序列化方式
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(
RedisSerializer.string()));
// 设置值的序列化方式,使用自定义的对象序列化器
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
buildRedisObjectSerializer()));
// 配置缓存项的生存时间
if (Objects.nonNull(redisProperties.getTimeToLive())) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
// 配置是否缓存空值
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
// 配置是否使用键前缀
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
// 返回配置好的 RedisCacheConfiguration
return config;
}
/**
* 构建自定义的 Redis 对象序列化器。
*
* @return
*/
private RedisSerializer<Object> buildRedisObjectSerializer() {
ObjectMapper om = new ObjectMapper();
// 设置所有属性的可见性
om.setVisibility(PropertyAccessor.ALL, Visibility.ANY);
// 启用默认的多态类型支持
om.activateDefaultTyping(om.getPolymorphicTypeValidator(), DefaultTyping.NON_FINAL);
// 禁用将日期键序列化为时间戳
om.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);
// 注册 Java 8 时间模块
om.registerModules(new JavaTimeModule());
return new GenericJackson2JsonRedisSerializer(om);
}
}
4. 常用注解
@Cacheable
作用
@Cacheable
注解添加在方法上,注解用于缓存方法的返回值。当方法被调用时,会首先检查缓存中是否已有结果。如果存在,则直接返回缓存中的结果;如果不存在,则执行方法,并将结果存入缓存。
参数含义
- cacheNames:缓存名,可以填写一个或多个缓存名。
- value: 和
cacheNames
属性相同,是它的别名。 - key: 用于指定缓存中条目的键。可以使用 SpEL 表达式来生成键。
- condition: 可选项,只有在条件满足时才会缓存结果。使用 SpEL 表达式。
- unless: 可选项,只有在条件不满足时才会缓存结果。使用 SpEL 表达式。
区别
@Cacheable
适用于只读操作,适合在数据未发生变化时使用,如查询操作。
@CachePut
作用
@CachePut
注解添加在方法上,注解用于将方法的返回值更新到缓存中。每次调用方法时,都会执行方法,并将返回值放入缓存,适用于更新或添加数据时。
参数含义
- cacheNames:缓存名,可以填写一个或多个缓存名。
- value: 和
cacheNames
属性相同,是它的别名。 - key: 用于指定缓存中条目的键,可以使用 SpEL 表达式。
- condition: 可选项,只有在条件满足时才会缓存结果。使用 SpEL 表达式。
- unless: 可选项,只有在条件不满足时才会缓存结果。使用 SpEL 表达式。
区别
@CachePut
适用于需要强制更新缓存的场景,适合用于修改操作。每次调用都会执行方法,无论缓存中是否存在数据。
@CacheEvict
作用
@CacheEvict
注解添加在方法上,注解用于从缓存中移除指定的条目。适用于数据被删除或更新时,确保缓存与数据库的同步。
参数含义
- cacheNames:缓存名,可以填写一个或多个缓存名。
- value: 和
cacheNames
属性相同,是它的别名。 - key: 用于指定缓存中条目的键,可以使用 SpEL 表达式。
- condition: 可选项,只有在条件满足时才会缓存结果。使用 SpEL 表达式。
- allEntries: 可选项,如果设置为
true
,将移除缓存中所有条目。使用 SpEL 表达式。
区别
@CacheEvict
主要用于删除缓存条目,适合在数据更新或删除后使用,以防止缓存中的数据过时。
小结
- @Cacheable: 用于读取数据,缓存方法的返回值。
- @CachePut: 用于更新数据,每次调用都会执行方法并更新缓存。
- @CacheEvict: 用于删除缓存中的条目,确保缓存数据的一致性。
5. 使用示例
常用的三个注解:@Cacheable
、@CachePut
和 @CacheEvict
。如下是使用示例:
@Service
public class UserService {
@Cacheable(cacheNames = "users")
public List<User> findUserById() {
// 查询数据库
return userMapper.selectList();
}
@CachePut(cacheNames = "users", key = "#user.userId")
public User updateUser(User user) {
// 更新用户数据
return user; // 返回更新后的用户
}
@CacheEvict(cacheNames = "users", key = "#userId")
public void deleteUser(Long userId) {
// 删除用户逻辑
}
}
5. 结论
本文介绍了在 Spring Boot 中使用缓存的基本方法,重点讲解了 @Cacheable
、@CachePut
和 @CacheEvict
注解的使用。通过合理地使用这些注解,可以显著提高应用程序的性能和响应速度。随着业务的复杂化,还可以根据需求选择合适的缓存提供者来满足性能和功能的需求。