public abstract class AbstractCacheWorker<T, Z> { @Resource protected RedisCommand redisCommand; /** * 读Redis缓存的实现 * * @param z 输入参数 * @return */ protected T read(Z z) { throw new IllegalArgumentException("read 方法未定义" + z); } /** * 批量读redis缓存的实现 * * @param z 输入参数 * @return 输出读取结果 */ protected List<T> batchRead(List<Z> z) { throw new IllegalArgumentException("batchRead 方法未定义" + z); } /** * 回源并写Redis缓存的实现 * * @param z 输入参数 * @return 输出回源结果 */ protected T write(Z z) { throw new IllegalArgumentException("write 方法未定义" + z); } /** * 回源并写Redis缓存的实现,自定义时间 Athony * * @param z * @param s 时间 * @return */ protected boolean write(Z z, int s) { throw new IllegalArgumentException("write 方法未定义" + z); } /** * 批量回源并写Redis缓存的实现 * * @param z 输入参数 * @return 输出回源结果 */ private Map<Z, T> batchWrite(List<Z> z, List<Integer> pos) { // 1. List<Z> keyOfNeedWriteList = new ArrayList<Z>(pos.size()); for (Integer i : pos) { keyOfNeedWriteList.add(z.get(i)); } return batchWrite(keyOfNeedWriteList); } protected Map<Z, T> batchWrite(List<Z> z) { throw new IllegalArgumentException("batchWrite 方法未定义"); } /** * 单条回源后,立即执行方法入口 * * @param t 输入对象 * @return 输出对象 */ protected T beforeReturn(T t) { return t; } /** * 批量回源后,立即执行方法入口 * * @param list 输入对象 * @return 输出对象 */ protected List<T> beforeBatchReturn(List<T> list) { return list; } /** * 执行批量查询的方法 * * @param list 输入参数 * @return 结果 */ @SuppressWarnings("all") public List<T> batchFind(List<Z> list) { if (list == null || list.isEmpty()) { return new ArrayList<T>(); } List<T> tList = batchRead(list); List<Integer> posList = nullPos(tList); if (!posList.isEmpty()) { Map<Z, T> tmpMap = batchWrite(list, posList); for (int i = 0; i < posList.size(); i++) { int pos = posList.get(i); tList.set(pos, tmpMap.get(list.get(pos))); } } return beforeBatchReturn(tList); } /** * 执行单条查询的方法 * * @param z 输入参数 * @return 结果 */ @SuppressWarnings("all") public T find(Z z) { if (z == null) { return null; } T t = read(z); if (t == null) { t = write(z); } return beforeReturn(t); } /** * 计算列表中为null的各元素位置 * * @param t 列表 * @return null元素位置列表 */ private List<Integer> nullPos(List<T> t) { List<Integer> posList = new ArrayList<Integer>(); for (int i = 0; i < t.size(); i++) { if (t.get(i) == null) { posList.add(i); } } return posList; } }
单查
find
/** * 执行单条查询的方法 * * @param z 输入参数 * @return 结果 */ @SuppressWarnings("all") public T find(Z z) { if (z == null) { return null; } T t = read(z); if (t == null) { t = write(z); } return beforeReturn(t); }
* 1) 读取 -(未找到)-> 回源 -> 写入 -> 返回<br>
* 2) 读取 -(找到)-> 返回
write
读链路如果检索到缓存中没有相关数据就会触发写链路
1)数据库中有对应数据 -> 批量写数据并设置过期时间 -> 返回结果
2)数据库中没有对应的数据 -> 设置相应的empty-key防止重复请求数据库.按照这种操作方式,需要在数据库中数据变更时,将对应的key和empty-key都删除,防止数据不同步 ->返回空结果
@Override protected T write(Z z) { String redisKey = ""; String emptyKey = ""; String result = testDao.get(z); if (StrUtil.isBlank(result)){ redisCommand.set(emptyKey,""); return empty_T; } redisCommand.set(redisKey,result); return T; }
read
缓存中有key或者empty-key -> 查询key -> 查询结果为空,证明时empty-key -> 返回empty -> 不需要查询数据库 -> 返回空结果
缓存中有key或者empty-key -> 查询key -> 查询结果不为空 -> 返回查询结果
缓存中没有 key和enpty-key -> 写链路写入相应的key或者empty-key -> 写链路返回结果
@Override protected T read(Z z) { String rediskey = ""; String emptyKey = ""; if (redisCommand.exists(emptyKey) || redisCommand.exists(rediskey)){ String s = redisCommand.get(rediskey); if (StrUtil.isBlank(s)){ return empty_T; } return T; } return null; }
beforeReturn
单挑记录查询之后立即执行beforeReturn中的方法。默认为空,可以自行织入相关逻辑