From 2ba05884bebdb85497b763606d154e82dc3db49f Mon Sep 17 00:00:00 2001 From: dongpx <2112323174@qq.com> Date: Fri, 6 Feb 2026 18:04:36 +0800 Subject: [PATCH] Signed-off-by: dongpx <2112323174@qq.com> --- .../top/lidee/taie/cache/CacheHelper.java | 327 +++++++++++ .../lidee/taie/cache/LideeCacheService.java | 248 ++++++++ .../lidee/taie/cache/RedisCacheHelper.java | 539 ++++++++++++++++++ 3 files changed, 1114 insertions(+) create mode 100644 lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/CacheHelper.java create mode 100644 lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/LideeCacheService.java create mode 100644 lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/RedisCacheHelper.java diff --git a/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/CacheHelper.java b/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/CacheHelper.java new file mode 100644 index 0000000..e52d4ca --- /dev/null +++ b/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/CacheHelper.java @@ -0,0 +1,327 @@ +package top.lidee.taie.cache; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * 缓存帮助类 + * @author lr + * @since 2021-01-12 + */ +public interface CacheHelper { + + /** + * 获取指定key的String类型缓存 + * @param key + * @return + */ + default String stringGet(String key) { + return null; + } + default Map stringMultiGet(List keys) { + return null; + } + + /** + * 获取指定key的String类型缓存 + * @param key + * @return + */ + default Boolean setIfAbsent(String key, String value) { + return false; + } + + + /** + * 增加1 + * @param key + * @return + */ + default Long increment(String key) { + return 0L; + } + + /** + * 设置失效时间 + * @param key + * @param timeUnit + * @param timeout + */ + default void expire(String key, TimeUnit timeUnit, Long timeout) { + } + + /** + * 增加1 + * @param key + * @return + */ + default Long increment(String key, Long step) { + return 0L; + } + + /** + * 是否存在指定KEY + * @param key + * @return + */ + default boolean exist(String key) { + return false; + } + + /** + * 模糊匹配 + * @param pattern + * @return + */ + default Set keys(String pattern) { + return new HashSet<>(); + } + + + /** + * 设置指定key的String类型缓存 + * @param key + * @param value 缓存值 + * @return + */ + default void stringSet(String key, String value) { + + } + + /** + * 设置指定key的String类型缓存,包含过期时间 + * @param key + * @param value + * @param time + * @param timeUnit 时间单位 + */ + default void stringSetExpire(String key, String value, long time, TimeUnit timeUnit) { + + } + + /** + * 去掉前后空格 + * @param key + * @return + */ + default String regKey(String key) { + return key.trim(); + //.toLowerCase(); + } + + + /** + * 设置指定key的String类型缓存,包含过期时间 + * @param key + * @param value + * @param seconds + */ + default void stringSetExpire(String key, String value, long seconds) { + } + + /** + * 获取指定key的hash缓存 + * @param key + * @return + */ + default Map hashGet(String key) { + return new HashMap<>(); + } + + /*** + * 获取指定key的hash中对应的值 + * + * @param key + * @param keys + * @return + */ + default List hashMultiGet(String key,Collection keys){ + return hashMultiGet(key,keys,false); + } + + /*** + * 获取指定key的hash中对应的值 + * + * @param key + * @param keys + * @param includeDisabled 是否包括已禁用的数据 + * @return + */ + default List hashMultiGet(String key,Collection keys,boolean includeDisabled){ + return null; + } + + /*** + * disabled key后缀 + * @return + */ + default String getDisabledKey(){ + return ":DISABLED"; + } + + /*** + * 批量获取hashSet + * @param key + * @param keys + * @param includeDisabled + * @return + */ + default Map multiGet(String key,List keys,boolean includeDisabled){ + List list = hashMultiGet(key,keys,includeDisabled); + Map ret = new HashMap<>(); + for(int i=0; i< keys.size();i++){ + if(Objects.isNull(list.get(i))){ + continue; + } + ret.put(keys.get(i),list.get(i)); + } + return ret; + } + + /** + * 获取指定key的hash中对应的值 + * @param key + * @param hashKey + * @return + */ + default String hashGetString(String key, String hashKey) { + return null; + } + + /** + * 删除Hash中指定key的值 + * @param key + * @param hashKey + * @return + */ + default void hashDel(String key, String hashKey) { + } + + + /** + * 删除Hash中指定key的值 + * @param key + * @param hashKeys + * @return + */ + default void hashBatchDel(String key, Set hashKeys) { + hashBatchDel(key,hashKeys,false); + } + + /** + * 删除Hash中指定key的值 + * @param key + * @param hashKeys + * @param toDisable 删除的数据 key-rename + * @return + */ + default void hashBatchDel(String key, Set hashKeys,boolean toDisable) { + + } + + /** + * 判断指定key的hash中包含指定hashKey + * @param key + * @param hashKey + * @return + */ + default boolean hashExist(String key, String hashKey) { + return false; + } + + /** + * 判断指定key的hash中包含指定hashKeys中任何一个 + * @param key + * @param hashKeys + * @return + */ + default boolean hashAnyExist(String key, String[] hashKeys) { + return false; + } + + + + /** + * 设置指定key的hash缓存 + * @param key + * @param hashKey + * @param hashValue + * @return + */ + default void hashSet(String key, String hashKey, String hashValue) { + + } + + + /** + * 设置指定key的hash缓存 + * @param hash + * @return + */ + default void hashSet(String key, Map hash) { + + } + default void hashMultiSet(Map map){ + + } + + /** + * 删除指定key + * @param key + * @return + */ + default boolean delete(String key) { + return false; + } + + /** + * 删除指定key + * @param keys + * @return + */ + default boolean delete(List keys) { + return false; + } + + /** + * 向集合中添加 + * @param key + * @param values + * @return + */ + default Long setAdd(String key, String[] values) { + return 0L; + } + + + /** + * 向集合中添加 + * @param key + * @param values + * @param clear 是否清空旧数据 + * @return + */ + default Long setAdd(String key, String[] values, boolean clear) { + return 0L; + } + + /** + * 返回对应key的集合 + * @param key + * @return + */ + default Set setMembers(String key) { + return new HashSet<>(); + } + + /** + * 判断集合中是否有对应的value + * @param key + * @param value + * @return + */ + default Boolean setExist(String key, String value) { + return false; + } + +} diff --git a/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/LideeCacheService.java b/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/LideeCacheService.java new file mode 100644 index 0000000..bc75ce6 --- /dev/null +++ b/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/LideeCacheService.java @@ -0,0 +1,248 @@ +package top.lidee.taie.cache; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import top.lidee.taie.annotation.HashKey; +import top.lidee.taie.annotation.HashValue; +import top.lidee.taie.bean.HashKeyValue; +import top.lidee.taie.constant.BaseOperationEnum; +import top.lidee.taie.utils.ApplicationContextUtils; +import top.lidee.taie.utils.LideeUtils; +import top.lidee.taie.utils.ReflectionUtils; + +/** + * 粗粒度的缓存服务,重构LideeBaseService + * @author WongBin + * @date 2023/4/11 + */ +public interface LideeCacheService { + + default String formatKey(String key,String[] replaceArray, Object entity) { + return LideeUtils.formatKey(key,replaceArray,entity); + } + + /*** + * 单行数据的缓存刷新 + * @param entity + * @param opr + */ + default void refreshCacheFields(T entity, BaseOperationEnum opr){ + //更新缓存 + Field[] declaredFields = ReflectionUtils.getAllFieldsArr(entity); + Map cacheMap = new HashMap<>(); + for(Field field : declaredFields) { + field.setAccessible(true); + Object value; + + if (field.isAnnotationPresent(HashKey.class)) { + try { + value = field.get(entity); + } catch (IllegalAccessException e) { + continue; + } + if (value == null) { + continue; + } + HashKey hashKey = field.getAnnotation(HashKey.class); + String key = hashKey.key(); + //判断key是否存在 + if (cacheMap.containsKey(key)) { + HashKeyValue hashKeyValue = cacheMap.get(key); + hashKeyValue.setKey(String.valueOf(value)); + hashKeyValue.setHashKey(hashKey); + } else { + HashKeyValue hashKeyValue = new HashKeyValue(); + hashKeyValue.setKey(String.valueOf(value)); + hashKeyValue.setHashKey(hashKey); + cacheMap.put(key, hashKeyValue); + } + } + + if (field.isAnnotationPresent(HashValue.class)) { + try { + value = field.get(entity); + } catch (IllegalAccessException e) { + continue; + } + if (value == null) { + continue; + } + HashValue hashValue = field.getAnnotation(HashValue.class); + String key = hashValue.key(); + //判断key是否存在 + if (cacheMap.containsKey(key)) { + HashKeyValue hashKeyValue = cacheMap.get(key); + hashKeyValue.setValue(String.valueOf(value)); + } else { + HashKeyValue hashKeyValue = new HashKeyValue(); + hashKeyValue.setValue(String.valueOf(value)); + cacheMap.put(key, hashKeyValue); + } + } + } + + //缓存操作类 + CacheHelper cacheHelper = ApplicationContextUtils.getBean(CacheHelper.class); + if (BaseOperationEnum.DELETE == opr || BaseOperationEnum.DELETE_BATCH == opr) { + //删除缓存 + cacheMap.entrySet().stream().filter(entry -> entry.getValue().nonNull()).forEach(entry -> { + String k = formatKey(entry.getKey(),entry.getValue().getHashKey().replace(), entity); + cacheHelper.hashDel(k, entry.getValue().getKey()); + }); + + } + if(BaseOperationEnum.INSERT == opr || BaseOperationEnum.UPDATE == opr){ + //刷新缓存,过滤掉HashKeyValue中,key为null或者value为null的情况 + cacheMap.entrySet().stream().filter(entry -> entry.getValue().nonNull()).forEach(entry -> { + String k = formatKey(entry.getKey(),entry.getValue().getHashKey().replace(), entity); + cacheHelper.hashSet(k, entry.getValue().getKey(), entry.getValue().getValue()); + }); + } + if(BaseOperationEnum.DELETE_INSERT == opr){ + //刷新缓存,过滤掉HashKeyValue中,key为null或者value为null的情况 + cacheMap.entrySet().stream().filter(entry -> entry.getValue().nonNull()).forEach(entry -> { + String k = formatKey(entry.getKey(),entry.getValue().getHashKey().replace(), entity); + cacheHelper.hashDel(k, entry.getValue().getKey()); + cacheHelper.hashSet(k, entry.getValue().getKey(), entry.getValue().getValue()); + }); + } + if(BaseOperationEnum.MERGE == opr){ + //刷新缓存,不过滤HashKeyValue中,key为null或者value为null的情况 + cacheMap.entrySet().stream().forEach(entry -> { + String k = formatKey(entry.getKey(),entry.getValue().getHashKey().replace(), entity); + //cacheHelper.hashDel(k, entry.getValue().getKey()); + cacheHelper.hashSet(k, entry.getValue().getKey(), entry.getValue().getValue()); + }); + } + } + + /*** + * 批量数据同步缓存 + * @param entities + * @param opr + */ + @SuppressWarnings("unchecked") + default void refreshCacheFieldsBatch(List entities, BaseOperationEnum opr){ + if(CollectionUtils.isEmpty(entities)){ + return; + } + T entity = entities.get(0); + Field[] declaredFields = ReflectionUtils.getAllFieldsArr(entity); + //缓存操作类 + CacheHelper cacheHelper = ApplicationContextUtils.getBean(CacheHelper.class); + + Map> cacheMap = new HashMap<>(); + for(T t : entities) { + // 先遍历一遍 hash-key + String namePrefix = ""; + String k = ""; + for (Field field : declaredFields) { + field.setAccessible(true); + Object value; + if (field.isAnnotationPresent(HashKey.class)) { + try { + value = field.get(t); + } catch (IllegalAccessException ex) { + continue; + } + if (value == null) { + continue; + } + HashKey hashKey = field.getAnnotation(HashKey.class); + String key = hashKey.key(); + namePrefix = formatKey(key, hashKey.replace(), t); + k = value+""; + if (cacheMap.containsKey(key)) { + Set list = cacheMap.get(key); + HashKeyValue r = new HashKeyValue(); + r.setKey(String.valueOf(value)); + r.setHashKey(hashKey); + r.setName(namePrefix); + list.add(r); + } else { + HashKeyValue kv = new HashKeyValue(); + kv.setKey(String.valueOf(value)); + kv.setHashKey(hashKey); + kv.setName(namePrefix); + Set list = new HashSet<>(); + list.add(kv); + cacheMap.put(key, list); + } + } + } + for (Field field : declaredFields) { + field.setAccessible(true); + Object value; + if (field.isAnnotationPresent(HashValue.class)) { + try { + value = field.get(t); + } catch (IllegalAccessException e) { + continue; + } + if (value == null) { + continue; + } + HashValue hashValue = field.getAnnotation(HashValue.class); + String key = hashValue.key(); + + if (cacheMap.containsKey(key)) { + Set list = cacheMap.get(key); + final String k1 = k; + final String ns = namePrefix; + list.stream().filter(f->f.getKey().equals(k1) && f.getName().equals(ns)) + .findFirst().get().setValue(String.valueOf(value)); + } + } + } + } + + if (BaseOperationEnum.DELETE == opr || BaseOperationEnum.DELETE_BATCH == opr) { + cacheMap.entrySet().stream().filter(entry -> !CollectionUtils.isEmpty(entry.getValue())).forEach(entry -> { + Map> map = entry.getValue().stream().collect(Collectors.groupingBy(t->t.getName())); + map.entrySet().forEach(kv->{ + cacheHelper.hashBatchDel(kv.getKey(),kv.getValue().stream().map(HashKeyValue::getKey).collect(Collectors.toSet())); + }); + }); + } + if(BaseOperationEnum.INSERT == opr || BaseOperationEnum.UPDATE == opr){ + cacheMap.entrySet().stream().filter(entry -> !CollectionUtils.isEmpty(entry.getValue())).forEach(entry -> { + Map> map = entry.getValue().stream().collect(Collectors.groupingBy(t->t.getName())); + map.entrySet().forEach(kv->{ + cacheHelper.hashSet(kv.getKey(),kv.getValue().stream() + .collect(Collectors.toMap(HashKeyValue::getKey,HashKeyValue::getValue,(v1,v2)->v2))); + }); + }); + } + if(BaseOperationEnum.DELETE_INSERT == opr){ + cacheMap.entrySet().stream().filter(entry -> !CollectionUtils.isEmpty(entry.getValue())).forEach(entry -> { + Map> map = entry.getValue().stream().collect(Collectors.groupingBy(t->t.getName())); + map.entrySet().forEach(kv->{ + cacheHelper.hashBatchDel(kv.getKey(),kv.getValue().stream().map(HashKeyValue::getKey).collect(Collectors.toSet())); + cacheHelper.hashSet(kv.getKey(),kv.getValue().stream() + .collect(Collectors.toMap(t->t.getKey(),t->t.getValue(),(v1,v2)->v2))); + }); + }); + } + if(BaseOperationEnum.MERGE == opr){ + cacheMap.entrySet().stream()/*.filter(entry -> !CollectionUtils.isEmpty(entry.getValue()))*/.forEach(entry -> { + Map> map = entry.getValue().stream().collect(Collectors.groupingBy(t->t.getName())); + map.entrySet().forEach(kv->{ + cacheHelper.hashSet(kv.getKey(),kv.getValue().stream() + .filter(e->!StringUtils.isEmpty(e.getKey())) + .collect(Collectors.toMap(t->t.getKey(), + t->Optional.ofNullable(t.getValue()).orElse(""),(v1,v2)->v2))); + }); + }); + } + } +} diff --git a/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/RedisCacheHelper.java b/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/RedisCacheHelper.java new file mode 100644 index 0000000..f3b2604 --- /dev/null +++ b/lidee-common/lidee-boot-taie/src/main/java/top/lidee/taie/cache/RedisCacheHelper.java @@ -0,0 +1,539 @@ +package top.lidee.taie.cache; + +import top.lidee.taie.constant.LideeConstant; + +import org.apache.commons.lang3.StringUtils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.BoundHashOperations; +import org.springframework.data.redis.core.BoundSetOperations; +import org.springframework.data.redis.core.BoundValueOperations; +import org.springframework.data.redis.core.ConvertingCursor; +import org.springframework.data.redis.core.Cursor; +import org.springframework.data.redis.core.ScanOptions; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @author lr + * @since 2021-06-22 + */ +public class RedisCacheHelper implements CacheHelper { + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + /** + * 获取指定key的String类型缓存 + * + * @param key + * @return + */ + @Override + public String stringGet(String key) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return ""; + } + BoundValueOperations operations = stringRedisTemplate.boundValueOps(regKey); + return operations.get(); + } + + @Override + public Map stringMultiGet(List keys) { + if(CollectionUtils.isEmpty(keys)){ + return Collections.emptyMap(); + } + List ret = stringRedisTemplate.opsForValue().multiGet(keys); + if(!CollectionUtils.isEmpty(ret)){ + Map map = new HashMap<>(); + for(int i=0;i operations = stringRedisTemplate.boundValueOps(regKey); + + return operations.setIfAbsent(value); + } + + + /** + * 增加1 + * + * @param key + * @return + */ + @Override + public Long increment(String key) { + String regKey = regKey(key); + BoundValueOperations operations = stringRedisTemplate.boundValueOps(regKey); + return operations.increment(); + } + + /** + * 设置失效时间 + * + * @param key + * @param timeUnit + * @param timeout + */ + @Override + public void expire(String key, TimeUnit timeUnit, Long timeout) { + String regKey = regKey(key); + stringRedisTemplate.expire(regKey, timeout, timeUnit); + } + + /** + * 增加1 + * + * @param key + * @return + */ + @Override + public Long increment(String key, Long step) { + BoundValueOperations operations = stringRedisTemplate.boundValueOps(regKey(key)); + return operations.increment(step); + } + + /** + * 是否存在指定KEY + * + * @param key + * @return + */ + @Override + public boolean exist(String key) { + return stringRedisTemplate.hasKey(regKey(key)); + } + + /** + * 模糊匹配, + * + * @param pattern + * @return + */ + @Override + public Set keys(String pattern) { + // 危险操作,线上可能会禁用该指令 + // return stringRedisTemplate.keys(pattern); + ScanOptions options = ScanOptions.scanOptions().count(1000).match(pattern).build(); + RedisSerializer redisSerializer = (RedisSerializer) stringRedisTemplate.getKeySerializer(); + Set result = new HashSet<>(); + try (Cursor cursor = stringRedisTemplate.executeWithStickyConnection( + redisConnection -> new ConvertingCursor<>(redisConnection.scan(options), redisSerializer::deserialize))) { + while (cursor.hasNext()) { + result.add(cursor.next().toString()); + } + } catch (Exception ex) { + + } + return result; + } + + + /** + * 设置指定key的String类型缓存 + * + * @param key + * @param value 缓存值 + * @return + */ + @Override + public void stringSet(String key, String value) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return; + } + BoundValueOperations operations = stringRedisTemplate.boundValueOps(regKey); + operations.set(value); + } + + /** + * 设置指定key的String类型缓存,包含过期时间 + * + * @param key + * @param value + * @param time + * @param timeUnit 时间单位 + */ + @Override + public void stringSetExpire(String key, String value, long time, TimeUnit timeUnit) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return; + } + BoundValueOperations operations = stringRedisTemplate.boundValueOps(regKey); + operations.set(value, time, timeUnit); + } + + /** + * 设置指定key的String类型缓存,包含过期时间 + * + * @param key + * @param value + * @param seconds + */ + @Override + public void stringSetExpire(String key, String value, long seconds) { + stringSetExpire(regKey(key), value, seconds, TimeUnit.SECONDS); + } + + /** + * 获取指定key的hash缓存 + * + * @param key + * @return + */ + @Override + public Map hashGet(String key) { + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey(key)); + + return operations.entries(); + } + + @Override + public List hashMultiGet(String key, Collection keys, boolean includeDisabled) { + if (Objects.isNull(key) || CollectionUtils.isEmpty(keys)) { + return Arrays.asList(""); + } + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey(key)); + List itemKeys = keys.stream().map(t -> regKey(t)).collect(Collectors.toList()); + List list = operations.multiGet(itemKeys); + for (int i = 0; i < list.size(); i++) { + list.set(i, Optional.ofNullable(list.get(i)).orElse("")); + } + if (includeDisabled) { + //list = list.stream().filter(i->StringUtils.isEmpty(i)).collect(Collectors.toList()); + Map nullKeys = new HashMap<>(); + for (int i = 0; i < list.size(); i++) { + if (StringUtils.isEmpty(list.get(i))) { + nullKeys.put(i, itemKeys.get(i)); + } + } + if (nullKeys.isEmpty()) { + return list; + } + // 查询禁用的数据 + BoundHashOperations d = + stringRedisTemplate.boundHashOps(regKey(key).concat(getDisabledKey())); + List nullItemKeys = new ArrayList<>(nullKeys.values()); + List disabledVals = d.multiGet(nullItemKeys); + if (!CollectionUtils.isEmpty(disabledVals)) { + Map dis = new HashMap<>(); + for (int i = 0; i < disabledVals.size(); i++) { + dis.put(nullItemKeys.get(i), Optional.ofNullable(disabledVals.get(i)).orElse("")); + } + // 替换为禁用的数据 + for (Entry src : nullKeys.entrySet()) { + list.set(src.getKey(), dis.get(src.getValue())); + } + } + } + return list; + } + + /** + * 获取指定key的hash中对应的值 + * + * @param key + * @param hashKey + * @return + */ + @Override + public String hashGetString(String key, String hashKey) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return ""; + } + String regHashKey = regKey(hashKey); + if (StringUtils.isBlank(regHashKey)) { + return ""; + } + + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey); + if (hashKey.contains(LideeConstant.SPLIT)) { + String[] split = hashKey.split(LideeConstant.SPLIT); + String reduce = Arrays.stream(split).reduce("", (all, item) -> { + if (StringUtils.isBlank(all)) { + all = operations.get(item); + } else { + all = all + "," + operations.get(item); + } + return all; + }); + return reduce; + } + + return operations.entries().get(regHashKey); + } + + /** + * 删除Hash中指定key的值 + * + * @param key + * @param hashKey + * @return + */ + @Override + public void hashDel(String key, String hashKey) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return; + } + String regHashKey = regKey(hashKey); + if (StringUtils.isBlank(regHashKey)) { + return; + } + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey); + operations.delete(regHashKey); + } + + + /** + * 删除Hash中指定key的值 + * + * @param key + * @param hashKeys + * @return + */ + @Override + public void hashBatchDel(String key, Set hashKeys, boolean toDisable) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey) || CollectionUtils.isEmpty(hashKeys)) { + return; + } + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey); + if (toDisable) { + BoundHashOperations disableOpt = stringRedisTemplate.boundHashOps(regKey.concat(getDisabledKey())); + List keys = hashKeys.stream().collect(Collectors.toList()); + List dels = operations.multiGet(hashKeys); + for (int i = 0; i < keys.size(); i++) { + disableOpt.put(keys.get(i), Optional.ofNullable(dels.get(i)).orElse("")); + } + } + + operations.delete(hashKeys.toArray(new String[0])); + } + + /** + * 判断指定key的hash中包含指定hashKey + * + * @param key + * @param hashKey + * @return + */ + @Override + public boolean hashExist(String key, String hashKey) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return false; + } + String regHashKey = regKey(hashKey); + if (StringUtils.isBlank(regHashKey)) { + return false; + } + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey); + return operations.hasKey(regHashKey); + } + + /** + * 判断指定key的hash中包含指定hashKeys中任何一个 + * + * @param key + * @param hashKeys + * @return + */ + @Override + public boolean hashAnyExist(String key, String[] hashKeys) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return false; + } + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey); + for (String hashKey : hashKeys) { + if (operations.hasKey(regKey(hashKey))) { + return true; + } + } + return false; + } + + + /** + * 设置指定key的hash缓存 + * + * @param key + * @param hashKey + * @param hashValue + * @return + */ + @Override + public void hashSet(String key, String hashKey, String hashValue) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey) || StringUtils.isBlank(hashKey)) { + return; + } + String regHashKey = regKey(hashKey); + if (StringUtils.isBlank(regHashKey) || StringUtils.isBlank(hashValue)) { + return; + } + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey); + operations.put(regHashKey, hashValue); + } + + + /** + * 设置指定key的hash缓存 + * + * @param hash + * @return + */ + @Override + public void hashSet(String key, Map hash) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return; + } + if (CollectionUtils.isEmpty(hash)) { + return; + } + BoundHashOperations operations = stringRedisTemplate.boundHashOps(regKey); + operations.putAll(hash); + } + + @Override + public void hashMultiSet(Map map) { + if(Objects.isNull(map) || map.isEmpty()){ + return; + } + stringRedisTemplate.opsForValue().multiSet(map); + } + + /** + * 删除指定key + * + * @param key + * @return + */ + @Override + public boolean delete(String key) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return false; + } + return stringRedisTemplate.delete(regKey); + } + + /** + * 删除指定key + * + * @param keys + * @return + */ + @Override + public boolean delete(List keys) { + if (CollectionUtils.isEmpty(keys)) { + return false; + } + + Long count = stringRedisTemplate.delete(keys.stream().map(t -> regKey(t)).collect(Collectors.toList())); + return count > 0; + } + + /** + * 向集合中添加 + * + * @param key + * @param values + * @return + */ + @Override + public Long setAdd(String key, String[] values) { + return setAdd(regKey(key), values, false); + } + + + /** + * 向集合中添加 + * + * @param key + * @param values + * @param clear 是否清空旧数据 + * @return + */ + @Override + public Long setAdd(String key, String[] values, boolean clear) { + String regKey = regKey(key); + if (clear) { + stringRedisTemplate.delete(regKey); + } + if (values != null && values.length == 0) { + return 0L; + } + BoundSetOperations setOperations = stringRedisTemplate.boundSetOps(regKey); + return setOperations.add(values); + } + + /** + * 返回对应key的集合 + * + * @param key + * @return + */ + @Override + public Set setMembers(String key) { + BoundSetOperations setOperations = stringRedisTemplate.boundSetOps(regKey(key)); + return setOperations.members(); + } + + /** + * 判断集合中是否有对应的value + * + * @param key + * @param value + * @return + */ + @Override + public Boolean setExist(String key, String value) { + String regKey = regKey(key); + if (StringUtils.isBlank(regKey)) { + return false; + } + + BoundSetOperations setOperations = stringRedisTemplate.boundSetOps(regKey); + return setOperations.isMember(value); + } +}