使用Supplier<T> 对方法结果进行缓存

本文介绍如何利用Java中的Supplier接口简化方法封装,通过缓存机制优化数据获取过程,减少重复计算,提高应用程序效率。

使用Supplier 可以对方法做个简单封装,比如对某个方法的返回结果进行缓存

1.Supplier 原型:get表示 返回一个类型为T的的方法

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

2.实现

import com.alibaba.fastjson.JSON;
import com.ctrip.car.osd.util.LogHelper;
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public class CacheHelper {
    private static final int EXPIREDSECOND = 60 * 10;//10 MINUTES
     /**
     * 
     * @param key 缓存key
     * @param supplier 需缓存结果的方法
     * @param classz 缓存数据的类型
     * @param <T>
     * @return
     */
    public static <T> List<T> getOrSetData(String key, Supplier<List<T>> supplier, Class classz) {
        List<T> list;
        try {
        	//修改成自己的缓存实现
        	//存在缓存则使用fastjson对缓存中的数据进行转换
            if (RedisManager.exists(key)) {
                list = JSON.parseArray(RedisManager.get(key), classz);
            } else {
            	//不存在缓存的则调用supplier,并且将结果存入缓存
                list = supplier.get();
                if (CollectionUtils.isNotEmpty(list)) {
                    RedisManager.set(key, JSON.toJSONString(list), EXPIREDSECOND);
                }
            }
        } catch (Exception ex) {
            LogHelper.error("CacheHelper.getOrSetData", ex);
            list = new ArrayList<>();
        }
        return list;
    }
}

3.使用例子

List<DataType> allList = CacheHelper.getOrSetData(CACHE_KEY, () -> getAllData(), Advertisement.class);
/*
//getAllData原型
List<Advertisement> getAllData() ;
*/
已经有如下代码,实现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 ); } } }
09-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值