一、前言
本地缓存大致流程可为:根据cacheKey去guava中查询数据,若存在,直接返回;若不存在,再去redis/mysql中查询,并把数据存到guava中......
可通过编写cacheUtil,把上述操作封装成一个方法,可供domain层任意处调用。虽然guava的key、value都是string类型,但我们封装的统一get方法的返回值是要string序列化之后的对象。为了满足不同返回值类型都能够使用封装完的get方法,可使用函数式编程 + 泛型进行编写。
二、CacheUtil
@Component
public class CacheUtil<V> {
private Cache<String, String> localCache = CacheBuilder.newBuilder()
.maximumSize(5000) //最大容量
.expireAfterWrite(10, TimeUnit.SECONDS) //最大容量、过期时间
.build();
/**
* @param cacheKey 缓存key
* @param clazz 声明json序列化类型
* @param function 由调用方自己写具体方法
* @return
*/
public List<V> getResult(String cacheKey, Class<V> clazz, Function<String, List<V>> function) {
String content = localCache.getIfPresent(cacheKey);
if(StringUtils.isNotBlank(content)) {
return JSON.parseArray(content, clazz);
}
List<V> resultList = function.apply(cacheKey);
if(!CollectionUtils.isEmpty(resultList)) {
localCache.put(cacheKey, JSON.toJSONString(resultList));
}
return resultList;
}
}
三、外部调用
@Override
@SneakyThrows
public List<SubjectCategoryBO> queryCategoryAndLabel(SubjectCategoryBO subjectCategoryBO) {
String cacheKey = "categoryAndLabel." + subjectCategoryBO.getId();
// List<SubjectCategoryBO> resultList = cacheUtil.getResult(cacheKey, SubjectCategoryBO.class, new Function<String, List>() {
// @Override
// public List apply(String key) {
// return getSubjectCategoryBOS(subjectCategoryBO.getId());
// }
// });
List<SubjectCategoryBO> resultList = cacheUtil.getResult(cacheKey, SubjectCategoryBO.class,
(key) -> getSubjectCategoryBOS(subjectCategoryBO.getId()));
return resultList;
}
只有第一次调用 和 超时10s后调用会控制台打印出sql, 10s内调用会返回guava中的数据,不走mysql