From 60fa1c3bfcc2def584d50b4f5e41113602c856bb Mon Sep 17 00:00:00 2001 From: Parker Date: Tue, 8 Dec 2020 15:41:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BC=93=E5=AD=98=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/constants/CacheConstants.java | 2 + .../org/opsli/core/aspect/CacheDataAop.java | 294 ++++++++++-------- .../opsli/core/base}/entity/HasChildren.java | 10 +- .../org/opsli/core/cache/local/CacheUtil.java | 18 +- .../cache/pushsub/entity/CacheDataEntity.java | 10 + .../core/cache/pushsub/enums/MsgArgsType.java | 5 + .../core/cache/pushsub/enums/PushSubType.java | 3 + .../cache/pushsub/handler/MenuHandler.java | 6 +- .../cache/pushsub/handler/OrgHandler.java | 76 +++++ .../cache/pushsub/msgs/OrgMsgFactory.java | 61 ++++ .../org/opsli/core/utils/CaptchaUtil.java | 19 +- .../java/org/opsli/core/utils/MenuUtil.java | 13 +- .../java/org/opsli/core/utils/OrgUtil.java | 183 +++++++++++ .../org/opsli/core/utils/UserTokenUtil.java | 26 +- .../java/org/opsli/core/utils/UserUtil.java | 43 ++- .../src/main/resources/creater.yaml | 4 + .../opsli/plugins/redis/lock/RedisLock.java | 17 +- .../src/main/resources/application.yaml | 20 +- 18 files changed, 637 insertions(+), 173 deletions(-) rename {opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/area => opsli-base-support/opsli-core/src/main/java/org/opsli/core/base}/entity/HasChildren.java (81%) create mode 100644 opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/OrgHandler.java create mode 100644 opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/msgs/OrgMsgFactory.java create mode 100644 opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/OrgUtil.java diff --git a/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/CacheConstants.java b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/CacheConstants.java index 4b12f15..a968deb 100644 --- a/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/CacheConstants.java +++ b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/CacheConstants.java @@ -24,6 +24,8 @@ package org.opsli.common.constants; */ public interface CacheConstants { + String PREFIX_NAME = "opsli"; + /** 热点数据 */ String HOT_DATA = "hotData"; diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/aspect/CacheDataAop.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/aspect/CacheDataAop.java index 10a6f9a..8f4018e 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/aspect/CacheDataAop.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/aspect/CacheDataAop.java @@ -15,6 +15,7 @@ */ package org.opsli.core.aspect; +import cn.hutool.core.collection.CollUtil; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; @@ -27,6 +28,7 @@ import org.opsli.common.annotation.hotdata.EnableHotData; import org.opsli.common.annotation.hotdata.HotDataDel; import org.opsli.common.annotation.hotdata.HotDataPut; import org.opsli.common.constants.CacheConstants; +import org.opsli.common.utils.Props; import org.opsli.core.cache.local.CacheUtil; import org.opsli.core.cache.pushsub.entity.CacheDataEntity; import org.opsli.core.cache.pushsub.enums.CacheType; @@ -57,7 +59,13 @@ import static org.opsli.common.constants.OrderConstants.HOT_DATA_ORDER; public class CacheDataAop { /** 热点数据前缀 */ - public static final String PREFIX_NAME = "opsli:"; + public static final String PREFIX_NAME; + static{ + // 缓存前缀 + Props props = new Props("application.yaml"); + PREFIX_NAME = props.getStr("spring.cache-conf.prefix",CacheConstants.PREFIX_NAME) + ":"; + } + @Autowired private RedisPlugin redisPlugin; @@ -80,33 +88,35 @@ public class CacheDataAop { public Object hotDataPutProcess(ProceedingJoinPoint point) throws Throwable { Object[] args= point.getArgs(); Object returnValue = point.proceed(args); - // 判断 方法上是否使用 HotData注解 如果没有表示开启热数据 则直接跳过 + // 判断 方法上是否使用 EnableHotData注解 如果没有表示开启热数据 则直接跳过 Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class); if(annotation == null){ return returnValue; } - // ====== 如果 使用了 EnableHotData ,表示开启热数据加载 则执行下段代码 - CacheDataEntity cacheDataEntity = this.putHandlerData(point, returnValue); - if(cacheDataEntity == null){ + List cacheDataEntityList = this.putHandlerData(point, returnValue); + // 非法判断 + if(CollUtil.isEmpty(cacheDataEntityList)){ return returnValue; } - // 更新缓存数据 - // 热点数据 - if(CacheConstants.HOT_DATA.equals(cacheDataEntity.getCacheName())){ - CacheUtil.putByKeyOriginal(cacheDataEntity.getKey(), returnValue); - } - // 永久数据 - else if(CacheConstants.EDEN_DATA.equals(cacheDataEntity.getCacheName())) { - CacheUtil.putEdenByKeyOriginal(cacheDataEntity.getKey(), returnValue); - } + for (CacheDataEntity cacheDataEntity : cacheDataEntityList) { + // 更新缓存数据 + // 热点数据 + if(CacheConstants.HOT_DATA.equals(cacheDataEntity.getCacheName())){ + CacheUtil.putByKeyOriginal(cacheDataEntity.getKey(), returnValue); + } + // 永久数据 + else if(CacheConstants.EDEN_DATA.equals(cacheDataEntity.getCacheName())) { + CacheUtil.putEdenByKeyOriginal(cacheDataEntity.getKey(), returnValue); + } - // 广播缓存数据 - 通知其他服务器同步数据 - redisPlugin.sendMessage( - CacheDataMsgFactory.createMsg(cacheDataEntity.getType(), - cacheDataEntity.getKey(), returnValue, CacheType.UPDATE) - ); + // 广播缓存数据 - 通知其他服务器同步数据 + redisPlugin.sendMessage( + CacheDataMsgFactory.createMsg(cacheDataEntity.getType(), + cacheDataEntity.getKey(), returnValue, CacheType.UPDATE) + ); + } return returnValue; } @@ -122,7 +132,7 @@ public class CacheDataAop { public Object hotDataDelProcess(ProceedingJoinPoint point) throws Throwable { Object[] args= point.getArgs(); Object returnValue = point.proceed(args); - // 判断 方法上是否使用 HotData注解 如果没有表示开启热数据 则直接跳过 + // 判断 方法上是否使用 EnableHotData注解 如果没有表示开启热数据 则直接跳过 Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class); if(annotation == null){ return returnValue; @@ -139,9 +149,9 @@ public class CacheDataAop { return returnValue; } - // ====== 如果 使用了 EnableHotData ,表示开启热数据加载 则执行下段代码 List cacheDataEntityList = this.delHandlerData(point, args); - if(cacheDataEntityList == null || cacheDataEntityList.size() == 0){ + // 非法判断 + if(CollUtil.isEmpty(cacheDataEntityList)){ return returnValue; } @@ -167,59 +177,44 @@ public class CacheDataAop { * PUT 处理数据 * @param point */ - private CacheDataEntity putHandlerData(ProceedingJoinPoint point, Object returnValue){ - CacheDataEntity ret; - // 返回值为空直接 - if(returnValue == null){ - return null; - } + private List putHandlerData(ProceedingJoinPoint point, Object returnValue){ // 这里 只对 继承了 ApiWrapper 的类做处理 if(!(returnValue instanceof ApiWrapper)){ return null; } + + // 消息集合 后续可能会考虑 多消息存储 + List cacheDataEntities = Lists.newArrayListWithCapacity(1); + // 报错不处理 try { - String methodName= point.getSignature().getName(); - Class classTarget= point.getTarget().getClass(); - Class[] par=((MethodSignature) point.getSignature()).getParameterTypes(); - Method objMethod = classTarget.getMethod(methodName, par); + // 获得方法 + Method objMethod = this.getMethod(point); + if(objMethod == null) return null; + // 获取注解参数 HotDataPut aCache= objMethod.getAnnotation(HotDataPut.class); if(aCache != null){ - // 类型 - PushSubType type; - // key 前缀 - StringBuilder keyBuf = new StringBuilder(PREFIX_NAME); - // 热点数据 - if(CacheConstants.HOT_DATA.equals(aCache.name())){ - keyBuf.append(CacheConstants.HOT_DATA).append(":"); - type = PushSubType.HOT_DATA; - } - // 系统数据 - else if(CacheConstants.EDEN_DATA.equals(aCache.name())){ - keyBuf.append(CacheConstants.EDEN_DATA).append(":"); - type = PushSubType.EDEN_DATA; - } else { + // 获得缓存类型 + PushSubType type = this.judgeCacheType(aCache.name()); + if(type == null) { // 如果都不是 则直接退出 不走缓存 return null; } + // key 前缀 + StringBuilder keyBuf = this.judgeCacheKeyBuf(aCache.name()); - try { - // 这里 只对 继承了 BaseEntity 的类做处理 - ApiWrapper apiWrapper = (ApiWrapper) returnValue; + // 这里 只对 继承了 BaseEntity 的类做处理 + ApiWrapper apiWrapper = (ApiWrapper) returnValue; - // key 存储ID - String key = keyBuf.append(apiWrapper.getId()).toString(); + // key 存储ID + String key = keyBuf.append(apiWrapper.getId()).toString(); - ret = new CacheDataEntity(); - ret.setKey(key); - ret.setType(type); - ret.setCacheName(aCache.name()); + CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name()); + // 存放数据 + this.putCacheData(cacheDataEntities, ret); - return ret; - }catch (Exception e){ - log.error(e.getMessage(),e); - } + return cacheDataEntities; } }catch (Exception e){ log.error(e.getMessage(),e); @@ -237,89 +232,67 @@ public class CacheDataAop { return null; } - // DEL 消息集合 + // 消息集合 List cacheDataEntities = Lists.newArrayListWithCapacity(args.length); // 报错不处理 try { - String methodName= point.getSignature().getName(); - Class classTarget= point.getTarget().getClass(); - Class[] par=((MethodSignature) point.getSignature()).getParameterTypes(); - Method objMethod = classTarget.getMethod(methodName, par); + // 获得方法 + Method objMethod = this.getMethod(point); + if(objMethod == null) return null; + // 获取注解参数 HotDataDel aCache= objMethod.getAnnotation(HotDataDel.class); if(aCache != null){ - // 类型 - PushSubType type; - // key 前缀 - StringBuilder keyBuf = new StringBuilder(PREFIX_NAME); - // 热点数据 - if(CacheConstants.HOT_DATA.equals(aCache.name())){ - keyBuf.append(CacheConstants.HOT_DATA).append(":"); - type = PushSubType.HOT_DATA; - } - // 系统数据 - else if(CacheConstants.EDEN_DATA.equals(aCache.name())){ - keyBuf.append(CacheConstants.EDEN_DATA).append(":"); - type = PushSubType.EDEN_DATA; - } else { + // 获得缓存类型 + PushSubType type = this.judgeCacheType(aCache.name()); + if(type == null) { // 如果都不是 则直接退出 不走缓存 return null; } - - try { - - // 处理数据 - for (Object arg : args) { - if (arg instanceof String) { + // key 前缀 + StringBuilder keyBuf = this.judgeCacheKeyBuf(aCache.name()); + + // 处理数据 + for (Object arg : args) { + if (arg instanceof String) { + // key 存储ID + String key = keyBuf.toString() + arg; + CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name()); + // 存放数据 + this.putCacheData(cacheDataEntities, ret); + } else if (arg instanceof String[]) { + String[] ids = (String[]) arg; + for (String id : ids) { // key 存储ID - String key = keyBuf.toString() + arg; - CacheDataEntity ret = new CacheDataEntity(); - ret.setKey(key); - ret.setType(type); - ret.setCacheName(aCache.name()); - cacheDataEntities.add(ret); - } else if (arg instanceof String[]) { - String[] ids = (String[]) arg; - for (String id : ids) { + String key = keyBuf.toString() + id; + CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name()); + // 存放数据 + this.putCacheData(cacheDataEntities, ret); + } + } else if (arg instanceof ApiWrapper) { + // key 存储ID + ApiWrapper apiWrapper = (ApiWrapper) arg; + String key = keyBuf.toString() + apiWrapper.getId(); + CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name()); + // 存放数据 + this.putCacheData(cacheDataEntities, ret); + } else if (arg instanceof Collection) { + try { + Collection baseEntityList = (Collection) arg; + for (ApiWrapper baseEntity : baseEntityList) { // key 存储ID - String key = keyBuf.toString() + id; - CacheDataEntity ret = new CacheDataEntity(); - ret.setKey(key); - ret.setType(type); - ret.setCacheName(aCache.name()); - cacheDataEntities.add(ret); - } - } else if (arg instanceof ApiWrapper) { - // key 存储ID - ApiWrapper apiWrapper = (ApiWrapper) arg; - String key = keyBuf.toString() + apiWrapper.getId(); - CacheDataEntity ret = new CacheDataEntity(); - ret.setKey(key); - ret.setType(type); - ret.setCacheName(aCache.name()); - cacheDataEntities.add(ret); - } else if (arg instanceof Collection) { - try { - Collection baseEntityList = (Collection) arg; - for (ApiWrapper baseEntity : baseEntityList) { - // key 存储ID - String key = keyBuf.toString() + baseEntity.getId(); - CacheDataEntity ret = new CacheDataEntity(); - ret.setKey(key); - ret.setType(type); - ret.setCacheName(aCache.name()); - cacheDataEntities.add(ret); - } - }catch (Exception e){ - log.error(e.getMessage(),e); + String key = keyBuf.toString() + baseEntity.getId(); + CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name()); + // 存放数据 + this.putCacheData(cacheDataEntities, ret); } + }catch (Exception e){ + log.error(e.getMessage(),e); } } - return cacheDataEntities; - }catch (Exception e){ - log.error(e.getMessage(),e); } + return cacheDataEntities; } }catch (Exception e){ log.error(e.getMessage(),e); @@ -327,4 +300,73 @@ public class CacheDataAop { return null; } + + // ===================== + + /** + * 获得方法 + * @param point + * @return + */ + private Method getMethod(ProceedingJoinPoint point){ + Method m = null; + try { + String methodName= point.getSignature().getName(); + Class classTarget= point.getTarget().getClass(); + Class[] par=((MethodSignature) point.getSignature()).getParameterTypes(); + m = classTarget.getMethod(methodName, par); + }catch (Exception ignored){} + return m; + } + + /** + * 存放数据 + * @param cacheDataList + * @param cacheData + */ + private void putCacheData(List cacheDataList, CacheDataEntity cacheData){ + // 非法判断 + if(CollUtil.isEmpty(cacheDataList)){ + return; + } + cacheDataList.add(cacheData); + } + + /** + * 判断缓存Key + * @param cacheName + * @return + */ + private StringBuilder judgeCacheKeyBuf(String cacheName){ + // key 前缀 + StringBuilder keyBuf = new StringBuilder(PREFIX_NAME); + // 热点数据 + if(CacheConstants.HOT_DATA.equals(cacheName)){ + keyBuf.append(CacheConstants.HOT_DATA).append(":"); + } + // 系统数据 + else if(CacheConstants.EDEN_DATA.equals(cacheName)){ + keyBuf.append(CacheConstants.EDEN_DATA).append(":"); + } + return keyBuf; + } + + /** + * 判断缓存类型 + * @param cacheName + * @return + */ + private PushSubType judgeCacheType(String cacheName){ + PushSubType type = null; + // 热点数据 + if(CacheConstants.HOT_DATA.equals(cacheName)){ + type = PushSubType.HOT_DATA; + } + // 系统数据 + else if(CacheConstants.EDEN_DATA.equals(cacheName)){ + type = PushSubType.EDEN_DATA; + } + return type; + } + } diff --git a/opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/area/entity/HasChildren.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/base/entity/HasChildren.java similarity index 81% rename from opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/area/entity/HasChildren.java rename to opsli-base-support/opsli-core/src/main/java/org/opsli/core/base/entity/HasChildren.java index dfe2b44..fbbb992 100755 --- a/opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/area/entity/HasChildren.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/base/entity/HasChildren.java @@ -13,29 +13,27 @@ * License for the specific language governing permissions and limitations under * the License. */ -package org.opsli.modulars.system.area.entity; +package org.opsli.core.base.entity; -import com.baomidou.mybatisplus.annotation.TableLogic; import lombok.Data; import lombok.EqualsAndHashCode; -import org.opsli.core.base.entity.BaseEntity; /** * @BelongsProject: opsli-boot * @BelongsPackage: org.opsli.modulars.system.area.entity * @Author: Parker * @CreateTime: 2020-11-28 18:59:59 - * @Description: 地域表 + * @Description: Tree表 */ @Data @EqualsAndHashCode(callSuper = false) -public class HasChildren{ +public class HasChildren { /** 父级主键 */ private String parentId; - /** 地域名称 */ + /** 下级数量 */ private Integer count; diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/local/CacheUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/local/CacheUtil.java index 1995d4d..aaec7ff 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/local/CacheUtil.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/local/CacheUtil.java @@ -25,6 +25,7 @@ import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ToStringBuilder; import org.opsli.common.constants.CacheConstants; +import org.opsli.common.utils.Props; import org.opsli.core.aspect.CacheDataAop; import org.opsli.plugins.cache.EhCachePlugin; import org.opsli.plugins.redis.RedisPlugin; @@ -65,18 +66,27 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER; @AutoConfigureAfter({RedisPlugin.class , EhCachePlugin.class}) public class CacheUtil { - public static final String JSON_KEY = "data"; - /** 空状态 key 前缀 */ - private static final String NIL_FLAG_PREFIX = "opsli:nil:"; - /** 热点数据缓存时间 秒 */ private static int ttlHotData = 60000; /** Redis插件 */ private static RedisPlugin redisPlugin; /** EhCache插件 */ private static EhCachePlugin ehCachePlugin; + /** Json key */ + public static final String JSON_KEY = "data"; + /** 空状态 key 前缀 */ + private static final String NIL_FLAG_PREFIX; + + /** 热点数据前缀 */ + public static final String PREFIX_NAME; static { + + // 缓存前缀 + Props props = new Props("application.yaml"); + PREFIX_NAME = props.getStr("spring.cache-conf.prefix",CacheConstants.PREFIX_NAME) + ":"; + NIL_FLAG_PREFIX = PREFIX_NAME + "nil:"; + try { // 读取配置信息 CacheUtil.readPropertyXML(); diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/entity/CacheDataEntity.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/entity/CacheDataEntity.java index 7fd2695..b248931 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/entity/CacheDataEntity.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/entity/CacheDataEntity.java @@ -15,7 +15,10 @@ */ package org.opsli.core.cache.pushsub.entity; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.opsli.core.cache.pushsub.enums.PushSubType; /** @@ -26,6 +29,8 @@ import org.opsli.core.cache.pushsub.enums.PushSubType; * @Description: 热点数据处理 Entity */ @Data +@AllArgsConstructor +@NoArgsConstructor public class CacheDataEntity { /** key */ @@ -37,4 +42,9 @@ public class CacheDataEntity { /** 缓存名称 */ private String cacheName; + + public static void main(String[] args) { + CacheDataEntity ret = new CacheDataEntity("123", PushSubType.EDEN_DATA, "12aaaa"); + System.out.println(ToStringBuilder.reflectionToString(ret)); + } } diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/MsgArgsType.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/MsgArgsType.java index 858872f..202a9f2 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/MsgArgsType.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/MsgArgsType.java @@ -47,6 +47,11 @@ public enum MsgArgsType { /** 菜单数据*/ MENU_MODEL_DATA, + /** 组织 用户ID */ + ORG_USER_ID, + /** 组织 用户数据 */ + ORG_USER_DATA, + /** 缓存数据Key */ CACHE_DATA_KEY, /** 缓存数据Value */ diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/PushSubType.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/PushSubType.java index c51ac3b..65ab27e 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/PushSubType.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/enums/PushSubType.java @@ -33,6 +33,9 @@ public enum PushSubType { /** 菜单数据 */ MENU, + /** 组织数据 */ + ORG, + /** 热点数据 */ HOT_DATA, diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/MenuHandler.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/MenuHandler.java index c0677e6..295e11d 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/MenuHandler.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/MenuHandler.java @@ -31,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired; * @BelongsPackage: org.opsli.core.cache.pushsub.handler * @Author: Parker * @CreateTime: 2020-09-15 16:24 - * @Description: 字典消息处理 + * @Description: 菜单消息处理 */ @Slf4j public class MenuHandler implements RedisPushSubHandler{ @@ -46,7 +46,7 @@ public class MenuHandler implements RedisPushSubHandler{ @Override public void handler(JSONObject msgJson) { - // 用户刷新 + // 菜单刷新 this.menuHandler(msgJson); } @@ -59,7 +59,7 @@ public class MenuHandler implements RedisPushSubHandler{ // 数据为空则不执行 if(data == null) return; - // 获得用户ID 和 用户名 + // 获得菜单编号 String menuCode = (String) msgJson.get(MsgArgsType.MENU_CODE.toString()); if(StringUtils.isEmpty(menuCode)){ return; diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/OrgHandler.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/OrgHandler.java new file mode 100644 index 0000000..e66fcf0 --- /dev/null +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/handler/OrgHandler.java @@ -0,0 +1,76 @@ +/** + * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.opsli.core.cache.pushsub.handler; + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.opsli.common.constants.CacheConstants; +import org.opsli.core.cache.local.CacheUtil; +import org.opsli.core.cache.pushsub.enums.MsgArgsType; +import org.opsli.core.cache.pushsub.enums.PushSubType; +import org.opsli.core.utils.MenuUtil; +import org.opsli.core.utils.OrgUtil; +import org.opsli.plugins.cache.EhCachePlugin; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @BelongsProject: opsli-boot + * @BelongsPackage: org.opsli.core.cache.pushsub.handler + * @Author: Parker + * @CreateTime: 2020-09-15 16:24 + * @Description: 用户组织消息处理 + */ +@Slf4j +public class OrgHandler implements RedisPushSubHandler{ + + @Autowired + EhCachePlugin ehCachePlugin; + + @Override + public PushSubType getType() { + return PushSubType.ORG; + } + + @Override + public void handler(JSONObject msgJson) { + // 用户刷新 + this.orgHandler(msgJson); + } + + /** + * 用户组织数据处理 + * @param msgJson + */ + private void orgHandler(JSONObject msgJson){ + JSONObject data = msgJson.getJSONObject(MsgArgsType.ORG_USER_DATA.toString()); + // 数据为空则不执行 + if(data == null) return; + + // 获得用户ID + String userId = (String) msgJson.get(MsgArgsType.ORG_USER_ID.toString()); + if(StringUtils.isEmpty(userId)){ + return; + } + + // 先删除 + ehCachePlugin.delete(CacheConstants.HOT_DATA, OrgUtil.PREFIX_CODE + userId); + // 清除空拦截 + CacheUtil.delNilFlag(OrgUtil.PREFIX_CODE + userId); + } + + +} diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/msgs/OrgMsgFactory.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/msgs/OrgMsgFactory.java new file mode 100644 index 0000000..a087312 --- /dev/null +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/pushsub/msgs/OrgMsgFactory.java @@ -0,0 +1,61 @@ +/** + * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.opsli.core.cache.pushsub.msgs; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.experimental.Accessors; +import org.opsli.api.wrapper.system.menu.MenuModel; +import org.opsli.api.wrapper.system.user.UserOrgRefModel; +import org.opsli.core.cache.pushsub.enums.MsgArgsType; +import org.opsli.core.cache.pushsub.enums.PushSubType; +import org.opsli.core.cache.pushsub.receiver.RedisPushSubReceiver; +import org.opsli.plugins.redis.pushsub.entity.BaseSubMessage; + +/** + * @BelongsProject: opsli-boot + * @BelongsPackage: org.opsli.core.cache.pushsub.msgs + * @Author: Parker + * @CreateTime: 2020-09-15 16:50 + * @Description: 用户组织消息 + */ + +@Data +@Accessors(chain = true) +public final class OrgMsgFactory extends BaseSubMessage{ + + /** 通道 */ + private static final String CHANNEL = RedisPushSubReceiver.BASE_CHANNEL+RedisPushSubReceiver.CHANNEL; + + private OrgMsgFactory(){} + + /** + * 构建消息 - 组织 + */ + public static BaseSubMessage createOrgMsg(UserOrgRefModel orgRefModel){ + BaseSubMessage baseSubMessage = new BaseSubMessage(); + // 数据 + JSONObject jsonObj = new JSONObject(); + jsonObj.put(MsgArgsType.ORG_USER_ID.toString(), orgRefModel.getUserId()); + jsonObj.put(MsgArgsType.ORG_USER_DATA.toString(), orgRefModel); + + // 用户 + baseSubMessage.build(CHANNEL,PushSubType.ORG.toString(),jsonObj); + return baseSubMessage; + } + + +} diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java index 7734f06..b84b240 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java @@ -18,7 +18,9 @@ package org.opsli.core.utils; import com.google.code.kaptcha.Producer; import org.apache.commons.lang3.StringUtils; import org.opsli.api.web.system.dict.DictDetailApi; +import org.opsli.common.constants.CacheConstants; import org.opsli.common.exception.TokenException; +import org.opsli.common.utils.Props; import org.opsli.core.msg.TokenMsg; import org.opsli.plugins.redis.RedisLockPlugins; import org.opsli.plugins.redis.RedisPlugin; @@ -45,13 +47,20 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER; public class CaptchaUtil{ /** 缓存前缀 */ - private static final String PREFIX = "opsli:temp:captcha:"; + private static final String PREFIX = "temp:captcha:"; /** 默认验证码保存 5 分钟 */ private static final int TIME_OUT = 300; /** Redis插件 */ private static RedisPlugin redisPlugin; /** 谷歌验证码 */ private static Producer producer; + /** 热点数据前缀 */ + public static final String PREFIX_NAME; + static{ + // 缓存前缀 + Props props = new Props("application.yaml"); + PREFIX_NAME = props.getStr("spring.cache-conf.prefix", CacheConstants.PREFIX_NAME) + ":"; + } /** * 获得验证码 @@ -66,7 +75,7 @@ public class CaptchaUtil{ //生成文字验证码 String code = producer.createText(); - boolean ret = redisPlugin.put(PREFIX + uuid, code, TIME_OUT); + boolean ret = redisPlugin.put(PREFIX_NAME + PREFIX + uuid, code, TIME_OUT); if(ret){ return producer.createImage(code); @@ -84,14 +93,14 @@ public class CaptchaUtil{ if(StringUtils.isEmpty(uuid)) return false; // 验证码 - String codeTemp = (String) redisPlugin.get(PREFIX + uuid); + String codeTemp = (String) redisPlugin.get(PREFIX_NAME + PREFIX + uuid); if(StringUtils.isEmpty(codeTemp)){ throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_NULL); } // 删除验证码 - //redisPlugin.del(PREFIX + uuid); + //redisPlugin.del(PREFIX_NAME + PREFIX + uuid); return codeTemp.equalsIgnoreCase(code); } @@ -106,7 +115,7 @@ public class CaptchaUtil{ if(StringUtils.isEmpty(uuid)) return false; //删除验证码 - return redisPlugin.del(PREFIX + uuid); + return redisPlugin.del(PREFIX_NAME + PREFIX + uuid); } diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/MenuUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/MenuUtil.java index f958e70..aa4421d 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/MenuUtil.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/MenuUtil.java @@ -23,6 +23,7 @@ import org.opsli.api.web.system.user.UserApi; import org.opsli.api.wrapper.system.menu.MenuModel; import org.opsli.core.cache.local.CacheUtil; import org.opsli.core.cache.pushsub.msgs.MenuMsgFactory; +import org.opsli.core.cache.pushsub.msgs.OrgMsgFactory; import org.opsli.plugins.redis.RedisLockPlugins; import org.opsli.plugins.redis.RedisPlugin; import org.opsli.plugins.redis.lock.RedisLock; @@ -58,7 +59,7 @@ public class MenuUtil { /** Redis分布式锁 */ private static RedisLockPlugins redisLockPlugins; - /** 用户Service */ + /** 菜单 Api */ private static MenuApi menuApi; @@ -139,13 +140,17 @@ public class MenuUtil { } MenuModel menuModel = CacheUtil.get(PREFIX_CODE + menu.getMenuCode(), MenuModel.class); + boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + menu.getMenuCode()); // 只要不为空 则执行刷新 - if (menuModel != null){ - // 先删除 - CacheUtil.del(PREFIX_CODE + menu.getMenuCode()); + if (hasNilFlag){ // 清除空拦截 CacheUtil.delNilFlag(PREFIX_CODE + menu.getMenuCode()); + } + + if(menuModel != null){ + // 先删除 + CacheUtil.del(PREFIX_CODE + menu.getMenuCode()); // 发送通知消息 redisPlugin.sendMessage( diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/OrgUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/OrgUtil.java new file mode 100644 index 0000000..5fd1fc4 --- /dev/null +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/OrgUtil.java @@ -0,0 +1,183 @@ +/** + * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.opsli.core.utils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.opsli.api.base.result.ResultVo; +import org.opsli.api.web.system.menu.MenuApi; +import org.opsli.api.web.system.user.UserApi; +import org.opsli.api.wrapper.system.menu.MenuModel; +import org.opsli.api.wrapper.system.user.UserOrgRefModel; +import org.opsli.core.cache.local.CacheUtil; +import org.opsli.core.cache.pushsub.msgs.MenuMsgFactory; +import org.opsli.core.cache.pushsub.msgs.OrgMsgFactory; +import org.opsli.plugins.redis.RedisLockPlugins; +import org.opsli.plugins.redis.RedisPlugin; +import org.opsli.plugins.redis.lock.RedisLock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.context.annotation.Lazy; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.opsli.common.constants.OrderConstants.UTIL_ORDER; + +/** + * @BelongsProject: opsli-boot + * @BelongsPackage: org.opsli.core.utils + * @Author: Parker + * @CreateTime: 2020-09-19 20:03 + * @Description: 组织机构工具类 + */ +@Slf4j +@Order(UTIL_ORDER) +@Component +@AutoConfigureAfter({RedisPlugin.class , RedisLockPlugins.class, UserApi.class}) +@Lazy(false) +public class OrgUtil { + + /** 前缀 */ + public static final String PREFIX_CODE = "org:userId:"; + + + /** Redis插件 */ + private static RedisPlugin redisPlugin; + + /** Redis分布式锁 */ + private static RedisLockPlugins redisLockPlugins; + + /** 用户 Api */ + private static UserApi userApi; + + + /** + * 根据 userId 获得用户组织 + * @param userId + * @return + */ + public static UserOrgRefModel getOrgByUserId(String userId){ + // 先从缓存里拿 + UserOrgRefModel orgRefModel = CacheUtil.get(PREFIX_CODE + userId, UserOrgRefModel.class); + if (orgRefModel != null){ + return orgRefModel; + } + + // 拿不到 -------- + // 防止缓存穿透判断 + boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + userId); + if(hasNilFlag){ + return null; + } + + // 锁凭证 redisLock 贯穿全程 + RedisLock redisLock = new RedisLock(); + redisLock.setLockName(PREFIX_CODE + userId) + .setAcquireTimeOut(3000L) + .setLockTimeOut(5000L); + + try { + // 这里增加分布式锁 防止缓存击穿 + // ============ 尝试加锁 + redisLock = redisLockPlugins.tryLock(redisLock); + if(redisLock == null){ + return null; + } + + // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 + orgRefModel = CacheUtil.get(PREFIX_CODE + userId, UserOrgRefModel.class); + if (orgRefModel != null){ + return orgRefModel; + } + + // 查询数据库 + ResultVo resultVo = userApi.getOrgInfoByUserId(userId); + if(resultVo.isSuccess()){ + orgRefModel = resultVo.getData(); + // 存入缓存 + CacheUtil.put(PREFIX_CODE + userId, orgRefModel); + } + }catch (Exception e){ + log.error(e.getMessage(),e); + }finally { + // ============ 释放锁 + redisLockPlugins.unLock(redisLock); + redisLock = null; + } + + if(orgRefModel == null){ + // 设置空变量 用于防止穿透判断 + CacheUtil.putNilFlag(PREFIX_CODE + userId); + return null; + } + + return orgRefModel; + } + + + // ============== 刷新缓存 ============== + + /** + * 刷新用户组织 - 删就完了 + * @param userId + * @return + */ + public static void refreshMenu(String userId){ + if(StringUtils.isEmpty(userId)){ + return; + } + + UserOrgRefModel orgRefModel = CacheUtil.get(PREFIX_CODE + userId, UserOrgRefModel.class); + boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + userId); + + // 只要不为空 则执行刷新 + if (hasNilFlag){ + // 清除空拦截 + CacheUtil.delNilFlag(PREFIX_CODE + userId); + } + + if(orgRefModel != null){ + // 先删除 + CacheUtil.del(PREFIX_CODE + userId); + + // 发送通知消息 + redisPlugin.sendMessage( + OrgMsgFactory.createOrgMsg(orgRefModel) + ); + } + } + + + + + // ===================================== + + @Autowired + public void setRedisPlugin(RedisPlugin redisPlugin) { + OrgUtil.redisPlugin = redisPlugin; + } + + @Autowired + public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) { + OrgUtil.redisLockPlugins = redisLockPlugins; + } + + @Autowired + public void setUserApi(UserApi userApi) { + OrgUtil.userApi = userApi; + } + +} diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java index 5270c68..000a391 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserTokenUtil.java @@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.shiro.crypto.hash.Md5Hash; import org.opsli.api.base.result.ResultVo; import org.opsli.api.wrapper.system.user.UserModel; +import org.opsli.common.constants.CacheConstants; import org.opsli.common.constants.SignConstants; import org.opsli.common.constants.TokenConstants; import org.opsli.common.exception.ServiceException; @@ -62,11 +63,11 @@ public class UserTokenUtil { /** token 缓存名 */ public static final String TOKEN_NAME = TokenConstants.ACCESS_TOKEN; /** 缓存前缀 */ - private static final String PREFIX = "opsli:ticket:"; + private static final String TICKET_PREFIX; /** 账号失败次数 */ - public static final String ACCOUNT_SLIP_COUNT_PREFIX = "opsli:account:slip:count:"; + public static final String ACCOUNT_SLIP_COUNT_PREFIX; /** 账号失败锁定KEY */ - public static final String ACCOUNT_SLIP_LOCK_PREFIX = "opsli:account:slip:lock:"; + public static final String ACCOUNT_SLIP_LOCK_PREFIX; /** 账号失败阈值 */ public static final int ACCOUNT_SLIP_COUNT; /** 账号失败N次后弹出验证码 */ @@ -77,15 +78,24 @@ public class UserTokenUtil { /** Redis插件 */ private static RedisPlugin redisPlugin; + /** 热点数据前缀 */ + public static final String PREFIX_NAME; - - static { + static{ + // 缓存前缀 Props props = new Props("application.yaml"); + PREFIX_NAME = props.getStr("spring.cache-conf.prefix", CacheConstants.PREFIX_NAME) + ":"; + TICKET_PREFIX = PREFIX_NAME + "ticket:"; + ACCOUNT_SLIP_COUNT_PREFIX = PREFIX_NAME + "account:slip:count:"; + ACCOUNT_SLIP_LOCK_PREFIX = PREFIX_NAME + "account:slip:lock:"; + + // 配置数据 ACCOUNT_SLIP_COUNT = props.getInt("opsli.login.slip-count", 5); ACCOUNT_SLIP_VERIFY_COUNT = props.getInt("opsli.login.slip-verify-count", 3); ACCOUNT_SLIP_LOCK_SPEED = props.getInt("opsli.login.slip-lock-speed", 300); } + /** * 根据 user 创建Token * @param user @@ -121,7 +131,7 @@ public class UserTokenUtil { // token 缓存真实失效时间 建议大于 最终时间 -- 多加了20分钟的失效时间 // 在redis存一份 token 是为了防止 认为造假 - boolean tokenFlag = redisPlugin.put(PREFIX + signTokenHex, endTimestamp, expire + 20); + boolean tokenFlag = redisPlugin.put(TICKET_PREFIX + signTokenHex, endTimestamp, expire + 20); if(tokenFlag){ map.put("token", signToken); map.put("expire", endTimestamp); @@ -177,7 +187,7 @@ public class UserTokenUtil { // 生成MD5 16进制码 用于缩减存储 String signTokenHex = new Md5Hash(token).toHex(); - redisPlugin.del(PREFIX + signTokenHex); + redisPlugin.del(TICKET_PREFIX + signTokenHex); // 删除相关信息 String userId = getUserIdByToken(token); @@ -209,7 +219,7 @@ public class UserTokenUtil { // 2. 校验当前缓存中token是否失效 // 生成MD5 16进制码 用于缩减存储 String signTokenHex = new Md5Hash(token).toHex(); - Long endTimestamp = (Long) redisPlugin.get(PREFIX + signTokenHex); + Long endTimestamp = (Long) redisPlugin.get(TICKET_PREFIX + signTokenHex); if(endTimestamp == null){ return false; } diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserUtil.java index 1d58d3a..39ade3b 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserUtil.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/UserUtil.java @@ -29,6 +29,7 @@ import org.opsli.common.api.TokenThreadLocal; import org.opsli.common.exception.TokenException; import org.opsli.common.utils.Props; import org.opsli.core.cache.local.CacheUtil; +import org.opsli.core.cache.pushsub.msgs.MenuMsgFactory; import org.opsli.core.cache.pushsub.msgs.UserMsgFactory; import org.opsli.core.msg.TokenMsg; import org.opsli.plugins.redis.RedisLockPlugins; @@ -537,6 +538,16 @@ public class UserUtil { UserModel userModelByUsername = CacheUtil.get(PREFIX_USERNAME + user.getUsername(), UserModel.class); + boolean hasNilFlagById = CacheUtil.hasNilFlag(PREFIX_ID + user.getId()); + boolean hasNilFlagByName = CacheUtil.hasNilFlag(PREFIX_USERNAME + user.getUsername()); + + // 只要有一个不为空 则执行刷新 + if (hasNilFlagById || hasNilFlagByName){ + // 清除空拦截 + CacheUtil.delNilFlag(PREFIX_ID + user.getId()); + CacheUtil.delNilFlag(PREFIX_USERNAME + user.getUsername()); + } + // 只要有一个不为空 则执行刷新 if (userModelById != null || userModelByUsername != null){ // 先删除 @@ -562,17 +573,24 @@ public class UserUtil { public static void refreshUserRoles(String userId){ try { Object obj = CacheUtil.get(PREFIX_ID_ROLES + userId); + boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_ROLES + userId); + + // 只要不为空 则执行刷新 + if (hasNilFlag){ + // 清除空拦截 + CacheUtil.delNilFlag(PREFIX_ID_ROLES + userId); + } + if(obj != null){ // 先删除 CacheUtil.del(PREFIX_ID_ROLES + userId); - // 清除空拦截 - CacheUtil.delNilFlag(PREFIX_ID_ROLES + userId); // 发送通知消息 redisPlugin.sendMessage( UserMsgFactory.createUserRolesMsg(userId, null) ); } + }catch (Exception e){ log.error(e.getMessage(), e); } @@ -586,11 +604,17 @@ public class UserUtil { public static void refreshUserAllPerms(String userId){ try { Object obj = CacheUtil.get(PREFIX_ID_PERMISSIONS + userId); + boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_PERMISSIONS + userId); + + // 只要不为空 则执行刷新 + if (hasNilFlag){ + // 清除空拦截 + CacheUtil.delNilFlag(PREFIX_ID_PERMISSIONS + userId); + } + if(obj != null){ // 先删除 CacheUtil.del(PREFIX_ID_PERMISSIONS + userId); - // 清除空拦截 - CacheUtil.delNilFlag(PREFIX_ID_PERMISSIONS + userId); // 发送通知消息 redisPlugin.sendMessage( @@ -610,17 +634,24 @@ public class UserUtil { public static void refreshUserMenus(String userId){ try { Object obj = CacheUtil.get(PREFIX_ID_MENUS + userId); + boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_MENUS + userId); + + // 只要不为空 则执行刷新 + if (hasNilFlag){ + // 清除空拦截 + CacheUtil.delNilFlag(PREFIX_ID_MENUS + userId); + } + if(obj != null){ // 先删除 CacheUtil.del(PREFIX_ID_MENUS + userId); - // 清除空拦截 - CacheUtil.delNilFlag(PREFIX_ID_MENUS + userId); // 发送通知消息 redisPlugin.sendMessage( UserMsgFactory.createUserMenusMsg(userId, null) ); } + }catch (Exception e){ log.error(e.getMessage(), e); } diff --git a/opsli-modulars/opsli-modulars-creater/src/main/resources/creater.yaml b/opsli-modulars/opsli-modulars-creater/src/main/resources/creater.yaml index daf9f08..9e16745 100644 --- a/opsli-modulars/opsli-modulars-creater/src/main/resources/creater.yaml +++ b/opsli-modulars/opsli-modulars-creater/src/main/resources/creater.yaml @@ -17,6 +17,10 @@ opsli: - sys_tenant - sys_user - sys_user_role_ref + - sys_area + - sys_org + - sys_org_user_ref + # 排除字段 exclude-fields: diff --git a/opsli-plugins/opsli-plugins-redis/src/main/java/org/opsli/plugins/redis/lock/RedisLock.java b/opsli-plugins/opsli-plugins-redis/src/main/java/org/opsli/plugins/redis/lock/RedisLock.java index 4fadd1d..daedf56 100644 --- a/opsli-plugins/opsli-plugins-redis/src/main/java/org/opsli/plugins/redis/lock/RedisLock.java +++ b/opsli-plugins/opsli-plugins-redis/src/main/java/org/opsli/plugins/redis/lock/RedisLock.java @@ -16,6 +16,9 @@ package org.opsli.plugins.redis.lock; +import org.opsli.common.constants.CacheConstants; +import org.opsli.common.utils.Props; + import java.util.concurrent.atomic.AtomicInteger; /** @@ -27,7 +30,17 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class RedisLock { - private static final String LOCK_PREFIX = "opsli:lock:"; + private static final String LOCK_PREFIX; + + /** 热点数据前缀 */ + public static final String PREFIX_NAME; + + static { + // 缓存前缀 + Props props = new Props("application.yaml"); + PREFIX_NAME = props.getStr("spring.cache-conf.prefix", CacheConstants.PREFIX_NAME) + ":"; + LOCK_PREFIX = PREFIX_NAME + "lock:"; + } /** 锁名称 */ private String lockName; @@ -44,8 +57,6 @@ public class RedisLock { /** 线程锁 */ private AtomicInteger atomicInteger; - - /** * 构造函数 */ diff --git a/opsli-starter/src/main/resources/application.yaml b/opsli-starter/src/main/resources/application.yaml index 0f59858..6ea2d27 100644 --- a/opsli-starter/src/main/resources/application.yaml +++ b/opsli-starter/src/main/resources/application.yaml @@ -66,7 +66,18 @@ spring: # 默认编码 default-encoding: UTF-8 - # 一级缓存 ---- redis 配置 + # 缓存配置项 + cache-conf: + # 前缀 + prefix: opsli + # 一级缓存 ---- EhCache 配置 + cache: + # 开启 是否启用本地缓存 + enable: true + # 加载配置文件 + jcache: + config: classpath:config/ehcache-opsli.xml + # 二级缓存 ---- Redis 配置 redis: # 开启消息订阅 pushsub: @@ -78,13 +89,6 @@ spring: max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 min-idle: 0 #最小等待连接中的数量,设 0 为没有限制 shutdown-timeout: 100ms - # 二级缓存 ---- EhCache 配置 - cache: - # 开启 是否启用本地缓存 - enable: true - # 加载配置文件 - jcache: - config: classpath:config/ehcache-opsli.xml # 数据库配置 datasource: