缓存工具类编写
一般操作
在外面日常开发中,经常会有为了减少数据库压力,而将数据保存到缓存中并设置一个过期时间的操作。日常代码如下:
@Autowired
private RedisTemplate<String, String> redisTemplate;public Object queryDataWithCache(String id) {String cacheKey = "cacheKey:" + id;String value = redisTemplate.opsForValue().get(cacheKey);Object result = null;if (ObjectUtil.isNotEmpty(value)) { // 缓存中存在数据,直接返回result = JsonUtil.getJsonToList(value, Object.class); // 将字符串转换为对应的类型} else { // 缓存中不存在数据,从数据库中查询result = queryFromDB(id); // 从数据库中查询数据String objectToString = JsonUtil.getObjectToString(result); // 将示例对象转换为json字符串redisTemplate.opsForValue().set(cacheKey, objectToString, 10L, TimeUnit.SECONDS); // 将数据保存到缓存中}return result;
}
通过代码可以发现,从缓存中取数据,和把数据保存缓存中的逻辑都是通用的,只有从数据库查询数据是不同的,我们可以把缓存操作抽取出来作为一个工具类使用,减少重复代码的编写。
缓存工具类编写
import cn.hutool.core.util.ObjectUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import tbea.util.JsonUtil;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;/*** @Description 本地缓存工具类* @Author ZengXi* @Date 2024/11/19*/
@Component
public class CacheUtils<V> @Autowiredprivate RedisTemplate<String, String> redisTemplate;/*** @description: 获取数据* @author ZengXi* @date 2024/11/19* @param cacheKey 缓存的key* @param clazz 返回类型* @param function 查询数据库操作的函数* @param expireTime 缓存过期时间* @return V*/public <V> V getResult(String cacheKey, Class<V> clazz, Supplier<V> function, int expireTime) {V result = null;String value = redisTemplate.opsForValue().get(cacheKey);if (ObjectUtil.isNotEmpty(value)) {result = JsonUtil.getJsonToBean(value, clazz);} else {result = function.get(); // 从数据库查询数据if (ObjectUtil.isNotEmpty(result)) {String objectToString = JsonUtil.getObjectToString(result);redisTemplate.opsForValue().set(cacheKey, objectToString, expireTime, TimeUnit.SECONDS);}}return result;}/*** @description: 获取数据列表* @author ZengXi* @date 2024/11/19* @param cacheKey 缓存的key* @param clazz 返回列表元素的类型* @param function 查询数据库操作的函数* @param expireTime 缓存过期时间* @return java.util.List<V>*/public List<V> getResultList(String cacheKey, Class<V> clazz, Supplier<List<V>> function,int expireTime) {String value = redisTemplate.opsForValue().get(cacheKey);List<V> resultList = new ArrayList<>();if (ObjectUtil.isNotEmpty(value)) {resultList = JsonUtil.getJsonToList(value, clazz);} else {resultList = function.get(); // 从数据库查询数据if (ObjectUtil.isNotEmpty(resultList)) {String objectToString = JsonUtil.getObjectToString(resultList);redisTemplate.opsForValue().set(cacheKey, objectToString, expireTime, TimeUnit.SECONDS);}}return resultList;}
}
工具类的使用
@Autowired
private CacheUtils cacheUtils;public Object queryDataWithCache(String id) {String cacheKey = "cacheKey:" + id;Object result = cacheUtils.getResult(cacheKey, Object.class, () -> queryFromDB(id), 10);return result;
}
总结
通过将查询数据库的函数作为传参,我们将缓存相关操作进行了抽取,减少了代码的编写,且如果后续需要更换缓存(如:将redis更换为把本地缓存),业务代码也不需要进行更改,只需要更改缓存工具类中的代码即可。