已经有如下代码,实现redis的数据缓存和取出
/**
* 通用缓存数据对象,支持任意数据类型
*
* @param <T> 缓存的数据类型
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaseCachedData<T> {
@Schema(description = "缓存ID", example = "USER_PROFILE_12345")
private String cacheId;
@Schema(description = "缓存数据对象", example = "{\"username\":\"john_doe\",\"email\":\"john@example.com\"}")
private T data;
@Schema(description = "缓存数据类型", example = "com.example.model.UserProfile")
private Class<T> dataType;
@Schema(description = "缓存创建时间戳", example = "1672531200000")
private long createdAt = Instant.now().toEpochMilli();
@Schema(description = "缓存过期时间(秒),0表示永不过期", example = "3600")
private long ttl = 0;
public <T> BaseCachedData(String cacheId, T data, Class<T> dataType) {
}
// 实用方法:检查缓存是否过期
public boolean isExpired() {
if (ttl <= 0) return false;
long currentTime = Instant.now().toEpochMilli();
return (currentTime - createdAt) > (ttl * 1000);
}
// 静态工厂方法
public static <T> BaseCachedData<T> of(String cacheId, T data, Class<T> dataType) {
return new BaseCachedData<>(cacheId, data, dataType);
}
public static <T> BaseCachedData<T> of(String cacheId, T data, Class<T> dataType, long ttl) {
return new BaseCachedData<>(cacheId, data, dataType, Instant.now().toEpochMilli(), ttl);
}
// 添加一个静态工厂方法用于刷新缓存
public static <T> BaseCachedData<T> refreshFrom(
BaseCachedData<?> original,
long newTtl
) {
// 获取原始数据的类型信息
Class<?> rawType = original.getDataType();
@SuppressWarnings("unchecked")
Class<T> dataType = (Class<T>) rawType;
// 获取原始数据并进行安全转换
@SuppressWarnings("unchecked")
T data = (T) original.getData();
return new BaseCachedData<>(
original.getCacheId(),
data,
dataType,
Instant.now().toEpochMilli(),
newTtl
);
}
}
@Configuration
@EnableCaching
public class RedisConfig {
// 1. 创建 RedisConnectionFactory Bean
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName("localhost");
config.setPort(6379);
config.setPassword("your-password");
config.setDatabase(0);
return new LettuceConnectionFactory(config);
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 配置缓存默认设置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30)) // 缓存有效期30分钟
.disableCachingNullValues() // 不缓存null值
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer())); // 使用JSON序列化
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(config)
.transactionAware() // 支持事务
.build();
}
@Bean
public RedisTemplate<String, BaseCachedData<?>> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, BaseCachedData<?>> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// 使用String序列化器作为Key序列化器
template.setKeySerializer(new StringRedisSerializer());
// 使用JSON序列化器作为Value序列化器
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
@Service
public class CacheServiceImpl implements CacheService {
private final RedisTemplate<String, BaseCachedData<?>> redisTemplate;
public CacheServiceImpl(RedisTemplate<String, BaseCachedData<?>> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public <T> BaseCachedData<T> cacheObject(String cacheId, T data, Class<T> dataType, long ttl) {
BaseCachedData<T> cachedData = new BaseCachedData<>(cacheId, data, dataType, Instant.now().toEpochMilli(), ttl);
redisTemplate.opsForValue().set(cacheId, cachedData, ttl, TimeUnit.SECONDS);
return cachedData;
}
@Override
public <T> Optional<BaseCachedData<T>> getCachedObject(String cacheId, Class<T> dataType) {
BaseCachedData<?> cachedData = redisTemplate.opsForValue().get(cacheId);
if (cachedData != null) {
// 检查和更新逻辑过期
if (cachedData.isExpired()) {
redisTemplate.delete(cacheId);
return Optional.empty();
}
return Optional.of((BaseCachedData<T>) cachedData);
}
return Optional.empty();
}
@Override
public <T> BaseCachedData<T> getOrCreate(String cacheId, Class<T> dataType, Supplier<T> supplier, long ttl) {
Optional<BaseCachedData<T>> cachedData = getCachedObject(cacheId, dataType);
if (cachedData.isPresent()) {
return cachedData.get();
}
T newData = supplier.get();
return cacheObject(cacheId, newData, dataType, ttl);
}
@Override
public void evictCache(String cacheId) {
redisTemplate.delete(cacheId);
}
@Override
public void refreshCache(String cacheId, long newTtl) {
BaseCachedData<?> cachedData = redisTemplate.opsForValue().get(cacheId);
if (cachedData != null && !cachedData.isExpired()) {
// 更新逻辑过期时间和Redis TTL
BaseCachedData<?> updatedData = BaseCachedData.refreshFrom(cachedData,newTtl);
redisTemplate.opsForValue().set(
cacheId,
updatedData,
newTtl,
TimeUnit.SECONDS
);
}
}
}
/**
* 通用缓存服务接口
*/
public interface CacheService {
/**
* 缓存单个对象
*
* @param cacheId 缓存ID
* @param data 要缓存的数据
* @param dataType 数据类型
* @param ttl 过期时间(秒)
* @param <T> 数据类型
* @return 缓存对象
*/
<T> BaseCachedData<T> cacheObject(String cacheId, T data, Class<T> dataType, long ttl);
/**
* 获取缓存对象
*
* @param cacheId 缓存ID
* @param dataType 数据类型
* @param <T> 数据类型
* @return Optional包装的缓存数据
*/
<T> Optional<BaseCachedData<T>> getCachedObject(String cacheId, Class<T> dataType);
/**
* 获取或创建缓存
*
* @param cacheId 缓存ID
* @param dataType 数据类型
* @param supplier 数据提供函数(当缓存不存在时调用)
* @param ttl 过期时间(秒)
* @param <T> 数据类型
* @return 缓存数据
*/
<T> BaseCachedData<T> getOrCreate(String cacheId, Class<T> dataType, Supplier<T> supplier, long ttl);
/**
* 删除缓存
*
* @param cacheId 缓存ID
*/
void evictCache(String cacheId);
/**
* 刷新缓存(更新过期时间)
*
* @param cacheId 缓存ID
* @param newTtl 新的过期时间(秒)
*/
void refreshCache(String cacheId, long newTtl);
}
@Service
public class CacheServiceImpl implements CacheService {
private final RedisTemplate<String, BaseCachedData<?>> redisTemplate;
public CacheServiceImpl(RedisTemplate<String, BaseCachedData<?>> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public <T> BaseCachedData<T> cacheObject(String cacheId, T data, Class<T> dataType, long ttl) {
BaseCachedData<T> cachedData = new BaseCachedData<>(cacheId, data, dataType, Instant.now().toEpochMilli(), ttl);
redisTemplate.opsForValue().set(cacheId, cachedData, ttl, TimeUnit.SECONDS);
return cachedData;
}
@Override
public <T> Optional<BaseCachedData<T>> getCachedObject(String cacheId, Class<T> dataType) {
BaseCachedData<?> cachedData = redisTemplate.opsForValue().get(cacheId);
if (cachedData != null) {
// 检查和更新逻辑过期
if (cachedData.isExpired()) {
redisTemplate.delete(cacheId);
return Optional.empty();
}
return Optional.of((BaseCachedData<T>) cachedData);
}
return Optional.empty();
}
@Override
public <T> BaseCachedData<T> getOrCreate(String cacheId, Class<T> dataType, Supplier<T> supplier, long ttl) {
Optional<BaseCachedData<T>> cachedData = getCachedObject(cacheId, dataType);
if (cachedData.isPresent()) {
return cachedData.get();
}
T newData = supplier.get();
return cacheObject(cacheId, newData, dataType, ttl);
}
@Override
public void evictCache(String cacheId) {
redisTemplate.delete(cacheId);
}
@Override
public void refreshCache(String cacheId, long newTtl) {
BaseCachedData<?> cachedData = redisTemplate.opsForValue().get(cacheId);
if (cachedData != null && !cachedData.isExpired()) {
// 更新逻辑过期时间和Redis TTL
BaseCachedData<?> updatedData = BaseCachedData.refreshFrom(cachedData,newTtl);
redisTemplate.opsForValue().set(
cacheId,
updatedData,
newTtl,
TimeUnit.SECONDS
);
}
}
}