package com.dobbinsoft.fw.support.component; import com.alibaba.fastjson.JSONObject; import com.dobbinsoft.fw.support.model.Page; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * Created by rize on 2019/3/22. */ @Component public class CacheComponent { @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired(required = false) private BeforeGetCacheKey beforeGetCacheKey; /** * 用于描述一系列的 将要执行的 Redis (写)操作 */ private ThreadLocal contextThreadLocal = new ThreadLocal<>(); /** * 放入不过期不序列化缓存 * * @param key * @param value */ public void putRaw(String key, String value) { stringRedisTemplate.opsForValue().set(getKey(key), value); } /** * 放入不过期不序列化缓存 * * @param key * @param value * @param expireSec */ public void putRaw(String key, String value, Integer expireSec) { stringRedisTemplate.opsForValue().set(getKey(key), value, expireSec, TimeUnit.SECONDS); } /** * 直接获取不反序列化缓存 * * @param key * @return */ public String getRaw(String key) { return stringRedisTemplate.opsForValue().get(getKey(key)); } /** * 放入对象/集合,进行序列化 * * @param key * @param obj */ public void putObj(String key, Object obj) { stringRedisTemplate.opsForValue().set(getKey(key), JSONObject.toJSONString(obj)); } /** * 放入对象/集合,进行序列化,带过期时间 * * @param key * @param obj * @param expireSec */ public void putObj(String key, Object obj, Integer expireSec) { stringRedisTemplate.opsForValue().set(getKey(key), JSONObject.toJSONString(obj), expireSec, TimeUnit.SECONDS); } /** * 获取对象进行序列化 * * @param key * @param clazz * @param * @return */ public T getObj(String key, Class clazz) { String json = stringRedisTemplate.opsForValue().get(getKey(key)); if (StringUtils.isEmpty(json)) { return null; } return JSONObject.parseObject(json, clazz); } /** * 获取对象列表 * * @param key * @param clazz * @param * @return */ public List getObjList(String key, Class clazz) { String json = stringRedisTemplate.opsForValue().get(getKey(key)); if (StringUtils.isEmpty(json)) { return null; } return JSONObject.parseArray(json, clazz); } /** * 将值放入Hash里 * * @param key * @param hashKey * @param value */ public void putHashRaw(String key, String hashKey, String value) { stringRedisTemplate.opsForHash().put(getKey(key), hashKey, value); } /** * 设置Hash对象,进行序列化 * * @param key * @param hashKey * @param obj */ public void putHashObj(String key, String hashKey, Object obj) { stringRedisTemplate.opsForHash().put(getKey(key), hashKey, JSONObject.toJSONString(obj)); } /** * 设置Hash对象,进行序列化 * * @param key * @param hashKey * @param obj * @param expireSec */ public void putHashObj(String key, String hashKey, Object obj, Integer expireSec) { String k = getKey(key); boolean hasKey = stringRedisTemplate.hasKey(k); stringRedisTemplate.opsForHash().put(k, hashKey, JSONObject.toJSONString(obj)); if (!hasKey) { stringRedisTemplate.expire(k, expireSec, TimeUnit.SECONDS); } } /** * 增加Hash表中键的字面数值 * * @param key * @param hashKey * @param delta * @return */ public long incrementHashKey(String key, String hashKey, long delta) { return stringRedisTemplate.opsForHash().increment(getKey(key), hashKey, delta); } /** * 减少Hash表中字面的数值 * * @param key * @param hashKey * @param delta * @return */ public long decrementHashKey(String key, String hashKey, long delta) { return stringRedisTemplate.opsForHash().increment(getKey(key), hashKey, -delta); } /** * 获取Hash值,不进行序列化 * * @param key * @param hashKey * @return */ public String getHashRaw(String key, String hashKey) { String o = (String) stringRedisTemplate.opsForHash().get(getKey(key), hashKey); if (StringUtils.isEmpty(o)) { return null; } return o; } /** * 获取Hash值,带反序列化 * * @param key * @param hashKey * @param clazz * @param * @return */ public T getHashObj(String key, String hashKey, Class clazz) { String o = (String) stringRedisTemplate.opsForHash().get(getKey(key), hashKey); if (StringUtils.isEmpty(o)) { return null; } return JSONObject.parseObject(o, clazz); } /** * 获取Hash值,以数组的形式反序列化 * * @param key * @param hashKey * @param clazz * @param * @return */ public List getHashList(String key, String hashKey, Class clazz) { String o = (String) stringRedisTemplate.opsForHash().get(getKey(key), hashKey); if (StringUtils.isEmpty(o)) { return null; } return JSONObject.parseArray(o, clazz); } /** * 批量获取Hash表里面的值 * * @param key 桶的名字 * @param hashKeys String类型键集合 Collection * @param clazz * @param * @return */ public List getHashMultiAsList(String key, Collection hashKeys, Class clazz) { List list = stringRedisTemplate.opsForHash().multiGet(getKey(key), hashKeys); return list.stream().map(item -> JSONObject.parseObject(item, clazz)).collect(Collectors.toList()); } /** * 批量获取Hash值 列表 * * @param key * @param hashKeys * @return */ public List getHashMultiAsRawList(String key, Collection hashKeys) { List list = stringRedisTemplate.opsForHash().multiGet(getKey(key), hashKeys); return list; } /** * 删除Hash值 * * @param key * @param hashKey */ public void delHashKey(String key, String hashKey) { stringRedisTemplate.opsForHash().delete(getKey(key), hashKey); } public void putHashAll(String key, Map map, Integer expireSec) { String k = getKey(key); stringRedisTemplate.opsForHash().putAll(k, map); stringRedisTemplate.expire(k, expireSec, TimeUnit.SECONDS); } public Map getHashAll(String key) { String k = getKey(key); if (!stringRedisTemplate.hasKey(k)) { return null; } return (Map)stringRedisTemplate.opsForHash().entries(k); } /** * 向有序集合中添加元素 * * @param setName * @param source * @param value */ public void putZSet(String setName, double source, String value) { stringRedisTemplate.opsForZSet().add(getKey(setName), value, source); } public void putZSetMulti(String setName, Set> values) { stringRedisTemplate.opsForZSet().add(getKey(setName), values); } /** * 从有序集合中移除数据 * * @param setName * @param value */ public void delZSet(String setName, String value) { stringRedisTemplate.opsForZSet().remove(getKey(setName), value); } /** * 从有序集合中分页获取数据 * * @param setName * @param pageNo * @param pageSize * @param isAsc * @return */ public Page getZSetPage(String setName, int pageNo, int pageSize, boolean isAsc) { String key = getKey(setName); Long size = stringRedisTemplate.opsForZSet().size(key); List list = new ArrayList<>(); if (size > 0) { if (isAsc) { list.addAll(stringRedisTemplate.opsForZSet().range(key, (pageNo - 1) * pageSize, pageNo * pageSize - 1)); } else { list.addAll(stringRedisTemplate.opsForZSet().reverseRange(key, (pageNo - 1) * pageSize, pageNo * pageSize - 1)); } } return new Page<>(list, pageNo, pageSize, size); } /** * 从有序集合中获取数据 * * @param setName * @param isAsc * @return */ public Set getZSetList(String setName, boolean isAsc) { String key = getKey(setName); Long size = stringRedisTemplate.opsForZSet().size(key); if (isAsc) { return stringRedisTemplate.opsForZSet().range(key, 0, size); } else { return stringRedisTemplate.opsForZSet().reverseRange(key, 0, size); } } /** * 设置Lru,最后进来的排最前面 * @param setName * @param value * @param max * @param exceed 可允许超出范围,清理缓存区。 */ public void putZSetLru(String setName, String value, int max, int exceed) { String key = getKey(setName); Long size = stringRedisTemplate.opsForZSet().size(key); if (size > max + exceed - 1) { //超过了。淘汰了 stringRedisTemplate.opsForZSet().removeRange(key, size - exceed, size); } stringRedisTemplate.opsForZSet().add(key, value, -System.currentTimeMillis()); } /** * 增加ZSet分数 * @param setName * @param value * @param delta */ public Double incZSetSource(String setName, String value, double delta) { return stringRedisTemplate.opsForZSet().incrementScore(getKey(setName), value, delta); } /** * 获取前N个 * @param setName * @param n * @return */ public Set getZSetLruTopN(String setName, int n) { return stringRedisTemplate.opsForZSet().range(getKey(setName), 0 , n); } /** * TODO 保证原子性问题 * 向一个set中添加数据 * @param key * @param member * @param expireSec */ public void putSetRaw(String key, String member, Integer expireSec) { stringRedisTemplate.opsForSet().add(getKey(key), member); stringRedisTemplate.expire(getKey(key), expireSec, TimeUnit.SECONDS); } /** * TODO 保证原子性问题 * @param key * @param set * @param expireSec */ public void putSetRawAll(String key, String[] set, Integer expireSec) { stringRedisTemplate.opsForSet().add(getKey(key), set); stringRedisTemplate.expire(getKey(key), expireSec, TimeUnit.SECONDS); } public void removeSetRaw(String key, String member) { stringRedisTemplate.opsForSet().remove(getKey(key), member); } public boolean isSetMember(String key, String member) { return stringRedisTemplate.opsForSet().isMember(getKey(key), member); } /** * 删除键 / 桶 / hash 表等 * * @param key */ public void del(String key) { stringRedisTemplate.delete(getKey(key)); } /** * 判断是否包含键 * * @param key * @return */ public boolean hasKey(String key) { return stringRedisTemplate.hasKey(getKey(key)); } /** * 获取指定前缀的Key * * @param prefix * @return */ public Set getPrefixKeySet(String prefix) { return stringRedisTemplate.keys(getKey(prefix) + "*"); } public void delPrefixKey(String prefix) { Set prefixKeySet = getPrefixKeySet(prefix); for (String key : prefixKeySet) { stringRedisTemplate.delete(key); } } /** * 获取redis中键的过期时间 * 返回秒 * @param key * @return */ public Long getKeyExpire(String key){ return stringRedisTemplate.getExpire(getKey(key)); } /** * 获取键 前置处理 * @param key * @return */ public String getKey(String key) { if (beforeGetCacheKey != null) { return beforeGetCacheKey.getKey(key); } return key; } public Collection getKeys(Collection keys) { if (beforeGetCacheKey != null) { return keys.stream().map(item -> { return beforeGetCacheKey.getKey(item); }).collect(Collectors.toList()); } return keys; } /** * 获取缓存上下文 * @return */ public CacheContext getCacheContext() { CacheContext cacheContext = this.contextThreadLocal.get(); if (cacheContext == null) { cacheContext = new CacheContext(); this.contextThreadLocal.set(cacheContext); } return cacheContext; } }