diff --git a/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/RedisConstants.java b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/RedisConstants.java index 836463fe..c12aef29 100644 --- a/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/RedisConstants.java +++ b/opsli-base-support/opsli-common/src/main/java/org/opsli/common/constants/RedisConstants.java @@ -19,10 +19,50 @@ public final class RedisConstants { public static final String PREFIX_MENU_CODE = "kv#{}:menu:code:"; /** 参数编号 */ - public static final String PREFIX_OPTIONS_CODE = "kv#{}:options:code"; + public static final String PREFIX_OPTIONS_CODE = "hash#{}:options"; /** 用户搜索记录 */ public static final String PREFIX_HIS_USERNAME = "zset#{}:his:username:"; + + + /** 用户ID */ + public static final String PREFIX_USER_ID = "kv#{}:user_id:"; + + /** 用户ID 和 角色 */ + public static final String PREFIX_USER_ID_AND_ROLES = "kv#{}:user_id:roles:"; + + /** 用户ID 和 默认角色 */ + public static final String PREFIX_USER_ID_DEF_ROLE = "kv#{}:user_id:def_role_id:"; + + /** 用户ID 和 组织 */ + public static final String PREFIX_USER_ID_ORGS = "kv#{}:user_id:orgs:"; + + /** 用户ID 和 默认组织 */ + public static final String PREFIX_USER_ID_DEF_ORG = "kv#{}:user_id:def_org:"; + + /** 用户ID 和 权限 */ + public static final String PREFIX_USER_ID_PERMISSIONS = "kv#{}:user_id:permissions:"; + + /** 用户ID 和 菜单 */ + public static final String PREFIX_USER_ID_MENUS = "kv#{}:user_id:menus:"; + + /** 用户名 */ + public static final String PREFIX_USERNAME = "kv#{}:username:"; + + + + /** 票据 */ + public static final String PREFIX_TICKET = "set#{}:ticket:"; + + /** 账号失败次数 */ + public static final String PREFIX_ACCOUNT_SLIP_COUNT = "kv#{}:account:slip:count:"; + + /** 账号失败锁定KEY */ + public static final String PREFIX_ACCOUNT_SLIP_LOCK = "kv#{}:account:slip:lock:"; + + + + private RedisConstants(){} } diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/RedisMessageListenerConfig.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/RedisMessageListenerConfig.java deleted file mode 100644 index 4f8d709a..00000000 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/RedisMessageListenerConfig.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * 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.autoconfigure.conf; - -import lombok.extern.slf4j.Slf4j; -import org.opsli.core.cache.pushsub.receiver.RedisPushSubReceiver; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.listener.PatternTopic; -import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; - - -/** - * 消息订阅 配置 - * - * @author Parker - * @date 2020-09-15 - **/ -@Slf4j -@Configuration -@ConditionalOnProperty(name = "spring.redis.pushsub.enable", havingValue = "true") -public class RedisMessageListenerConfig { - - - /** - * redis消息监听器容器 - * 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器 - * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理 - */ - @Bean - public RedisMessageListenerContainer container(LettuceConnectionFactory lettuceConnectionFactory) { - RedisPushSubReceiver receiver = new RedisPushSubReceiver(); - RedisMessageListenerContainer container = new RedisMessageListenerContainer(); - container.setConnectionFactory(lettuceConnectionFactory); - - //订阅了的通道 - container.addMessageListener(listenerAdapter(new RedisPushSubReceiver()), new PatternTopic(receiver.getListenerChannel())); - - return container; - } - - - /** - * 消息监听器适配器,绑定消息处理器,利用反射技术调用消息处理器的业务方法 - * 想要处理消息 需要重写 消息接受方法 - * - */ - @Bean - public MessageListenerAdapter listenerAdapter(RedisPushSubReceiver baseReceiver) { - //这个地方 是给messageListenerAdapter 传入一个消息接受的处理器,利用反射的方法调用“receiveMessage” - //也有好几个重载方法,这边默认调用处理器的方法 叫handleMessage 可以自己到源码里面看 - //receiveMessage就是对应消费者那边的消费方法吗,而Receiver是自己弄的一个消费者类 - return new MessageListenerAdapter(baseReceiver, "receiveMessage"); - } - -} diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/properties/CacheProperties.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/properties/CacheProperties.java index e9b28b08..38ea5651 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/properties/CacheProperties.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/properties/CacheProperties.java @@ -32,7 +32,7 @@ import org.springframework.stereotype.Component; @EqualsAndHashCode(callSuper = false) public class CacheProperties { - public static final String PROP_PREFIX = "spring.cache-conf"; + public static final String PROP_PREFIX = "spring.cache"; /** 缓存前缀 */ private String prefix; diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/base/controller/BaseRestController.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/base/controller/BaseRestController.java index d78fbcfe..3f3f547e 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/base/controller/BaseRestController.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/base/controller/BaseRestController.java @@ -37,30 +37,24 @@ import org.opsli.api.base.warpper.ApiWrapper; import org.opsli.api.wrapper.system.user.UserModel; import org.opsli.common.annotation.RequiresPermissionsCus; import org.opsli.common.annotation.hotdata.EnableHotData; -import org.opsli.common.constants.CacheConstants; import org.opsli.common.constants.TreeConstants; import org.opsli.common.enums.ExcelOperate; import org.opsli.common.exception.ServiceException; import org.opsli.common.exception.TokenException; -import org.opsli.common.msg.CommonMsg; import org.opsli.common.utils.OutputStreamUtil; import org.opsli.common.utils.WrapperUtil; import org.opsli.core.autoconfigure.properties.GlobalProperties; import org.opsli.core.base.entity.BaseEntity; import org.opsli.core.base.entity.HasChildren; import org.opsli.core.base.service.interfaces.CrudServiceInterface; -import org.opsli.core.cache.CacheUtil; import org.opsli.core.msg.CoreMsg; import org.opsli.core.msg.TokenMsg; import org.opsli.core.security.shiro.realm.JwtRealm; -import org.opsli.core.utils.DistributedLockUtil; import org.opsli.core.utils.ExcelUtil; import org.opsli.core.utils.UserUtil; import org.opsli.plugins.excel.exception.ExcelPluginException; import org.opsli.plugins.excel.listener.BatchExcelListener; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; @@ -98,90 +92,6 @@ public abstract class BaseRestController 泛型 - */ - public static V getTimed(final Class vClass, final String key){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 转换数据泛型 - return CacheUtil.get(vClass, key, false, false); - } - - /** - * 获得 普通 缓存 - * @param vClass 泛型Class - * @param key 键 - * @param isSaveLocal 是否保存到本地 - * @return 泛型 - */ - public static V getTimed(final Class vClass, final String key, - final boolean isSaveLocal){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 转换数据泛型 - return CacheUtil.get(vClass, key, false, isSaveLocal); - } - - /** - * 获得 普通 缓存 - * @param key 键 - * @return Object - */ - public static Object getEden(final String key){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 转换数据泛型 - return CacheUtil.get(key, true, false); - } - - /** - * 获得 普通 缓存 - * @param key 键 - * @param isSaveLocal 是否保存到本地 - * @return Object - */ - public static Object getEden(final String key, final boolean isSaveLocal){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 转换数据泛型 - return CacheUtil.get(key, true, isSaveLocal); - } - - /** - * 获得 普通 缓存 - * @param vClass 泛型Class - * @param key 键 - * @return 泛型 - */ - public static V getEden(final String key, final Class vClass){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 转换数据泛型 - return CacheUtil.get(vClass, key, true, false); - } - - /** - * 获得 普通 缓存 - * @param vClass 泛型Class - * @param key 键 - * @param isSaveLocal 是否保存到本地 - * @return 泛型 - */ - public static V getEden(final String key, final boolean isSaveLocal, - final Class vClass){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 转换数据泛型 - return CacheUtil.get(vClass, key, true, isSaveLocal); - } - - /** - * 获得 普通 缓存 - * @param vClass 泛型Class - * @param key 键 - * @param isEden 是否永久层数据 - * @param isSaveLocal 是否保存到本地 - * @return 泛型 - */ - private static V get(final Class vClass, final String key, final boolean isEden, - final boolean isSaveLocal){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 获得缓存数据 - Object cacheObj = CacheUtil.get(key, isEden, isSaveLocal); - // 转换数据泛型 - return Convert.convert(vClass, cacheObj); - } - - /** - * 获得 普通 缓存 - * @param key 键 - * @param isEden 是否永久层数据 - * @param isSaveLocal 是否保存到本地 - * @return Object - */ - private static Object get(final String key, final boolean isEden, final boolean isSaveLocal){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - try { - // 缓存 Key - String cacheKey = CacheUtil.handleUsualKey(key, isEden); - - // 获得缓存Json - JSONObject cacheJson; - - // 判读是否需要 先从本地缓存获取 - if(isSaveLocal){ - // 获得缓存Json - cacheJson = ehCachePlugin.get(CacheConstants.EHCACHE_SPACE, - cacheKey, JSONObject.class); - if(cacheJson != null){ - return cacheJson.get(JSON_KEY); - } - } - - // 如果本地缓存找不到该缓存 则去远端缓存拉去缓存 - cacheJson = (JSONObject) redisPlugin.get(cacheKey); - if(cacheJson != null){ - // 判读是否需要 存入本地EhCache - if(isSaveLocal){ - //存入EhCache - ehCachePlugin.put(CacheConstants.EHCACHE_SPACE, - cacheKey, cacheJson); - } - } - - return cacheJson != null ? cacheJson.get(JSON_KEY) : null; - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return null; - } - - - - /** - * 获得 Hash 缓存 - * @param vClass 泛型Class - * @param key 键 - * @param field 字段名 - * @return 泛型 - */ - public static V getHash(final Class vClass, final String key, final String field){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 获得缓存数据 - Object cacheObj = CacheUtil.getHash(key, field, false); - // 转换数据泛型 - return Convert.convert(vClass, cacheObj); - } - - /** - * 获得 Hash 缓存 - * @param key 键 - * @param field 字段名 - * @param isSaveLocal 是否保存到本地 - * @param vClass 泛型Class - * @return 泛型 - */ - public static V getHash(final Class vClass, final String key, - final String field, final boolean isSaveLocal){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 获得缓存数据 - Object cacheObj = CacheUtil.getHash(key, field, isSaveLocal); - // 转换数据泛型 - return Convert.convert(vClass, cacheObj); - } - - /** - * 获得 Hash 缓存 - * @param key 键 - * @param field 字段名 - * @return Object - */ - public static Object getHash(final String key, final String field){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - return CacheUtil.getHash(key, field, false); - } - - /** - * 获得 Hash 缓存 - * @param key 键 - * @param field 字段名 - * @param isSaveLocal 是否保存到本地 - * @return Object - */ - public static Object getHash(final String key, final String field, - final boolean isSaveLocal){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - try { - // 缓存 Key - String cacheKey = CacheUtil.handleKey(CacheType.EDEN_HASH, key); - - // 获得缓存Json - JSONObject cacheJson; - - // 判读是否需要 先从本地缓存获取 - if(isSaveLocal){ - // 获得缓存Json - cacheJson = ehCachePlugin.get(CacheConstants.EHCACHE_SPACE, - cacheKey +":"+ field, JSONObject.class); - if(cacheJson != null){ - return cacheJson.get(JSON_KEY); - } - } - - // 如果本地缓存找不到该缓存 则去远端缓存拉去缓存 - cacheJson = (JSONObject) redisPlugin.hGet(cacheKey, field); - if(cacheJson != null){ - // 判读是否需要 存入本地EhCache - if(isSaveLocal){ - //存入EhCache - ehCachePlugin.put(CacheConstants.EHCACHE_SPACE, - cacheKey + ":" + field, cacheJson); - } - } - - return cacheJson != null ? cacheJson.get(JSON_KEY) : null; - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return null; - } - - - /** - * 获得 Hash 缓存 - * @param key 键 - * @return Object - */ - public static Map getHashAll(final String key){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - try { - // 缓存 Key - String cacheKey = CacheUtil.handleKey(CacheType.EDEN_HASH, key); - - Map retMap = Maps.newHashMap(); - - // 如果本地缓存找不到该缓存 则去远端缓存拉去缓存 - Map allCache = redisPlugin.hGetAll(cacheKey); - if(CollUtil.isEmpty(allCache)){ - return retMap; - } - - for (Map.Entry entry : allCache.entrySet()) { - // 赋值 - JSONObject jsonObject = (JSONObject) entry.getValue(); - if (jsonObject == null) { - continue; - } - Object data = jsonObject.get(CacheUtil.JSON_KEY); - if (data == null) { - continue; - } - - retMap.put(Convert.toStr(entry.getKey()), data); - } - - return retMap; - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return null; - } - - // ========================= PUT ========================= - - - /** - * 存普通缓存 - * @param key 键 - * @param value 值 - * @return boolean - */ - public static boolean put(final String key, final Object value) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - return CacheUtil.put(key, value, false); - } - - /** - * 存永久缓存 - * @param key 键 - * @param value 值 - * @param isEden 是否永久存储 - * @return boolean - */ - public static boolean put(final String key, final Object value, final boolean isEden) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - try { - // 自动处理 key - - // 则统一转换为 JSONObject - JSONObject cacheJson = new JSONObject(); - cacheJson.put(JSON_KEY, value); - - // 缓存 Key - String cacheKey = CacheUtil.handleUsualKey(key, isEden); - - // 判断是否为永久存储 - if(isEden) { - // 存入Redis - return redisPlugin.put(cacheKey, cacheJson); - }else{ - // 随机缓存失效时间 防止缓存雪崩 - // 范围在当前时效的 1.2 - 2倍 - - // 生成随机失效时间 - int timeout = RandomUtil.randomInt( - Convert.toInt(TTL_HOT_DATA_TIME * 1.2), - Convert.toInt(TTL_HOT_DATA_TIME * 2) - ); - - // 存入Redis - return redisPlugin.put(cacheKey, cacheJson, timeout); - } - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return false; - } - - - - /** - * 存 永久 Hash 缓存 - * @param key 键 - * @param field 字段名 - * @param value 值 - * @return boolean - */ - public static boolean putHash(final String key, final String field, final Object value) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - try { - // 处理 key - String cacheKey = CacheUtil.handleKey(CacheType.EDEN_HASH, key); - - // 则统一转换为 JSONObject - JSONObject cacheJson = new JSONObject(); - cacheJson.put(JSON_KEY, value); - - // 存入Redis - return redisPlugin.hPut(cacheKey, field, cacheJson); - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return false; - } - - - // ========================= DEL ========================= - - - /** - * 删缓存 - * @param key 键 - * @return boolean - */ - public static boolean del(final String key) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - try { - // 计数器 - int count = 0; - - Object timed = CacheUtil.getTimed(key); - Object eden = CacheUtil.getEden(key); - - // 删除key 集合 - List cacheKeys = Lists.newArrayList(); - if(timed != null){ - count+=2; - // 处理 key - 时控数据 - cacheKeys.add( - CacheUtil.handleKey(CacheType.TIMED, key) - ); - } - if(eden != null){ - count+=2; - // 处理 key - 永久数据 - cacheKeys.add( - CacheUtil.handleKey(CacheType.EDEN, key)); - } - - // 循环删除缓存数据 - for (String cacheKey : cacheKeys) { - - // 删除 EhCache - boolean ehcacheRet = ehCachePlugin.delete(CacheConstants.EHCACHE_SPACE, cacheKey); - if(ehcacheRet){ - count--; - } - - // 删除 Redis - boolean redisRet = redisPlugin.del(cacheKey); - if(redisRet){ - count--; - } - } - - return count == 0; - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return false; - } - - /** - * 删 Hash 缓存 - * @param key 键 - * @param field 字段名 - * @return boolean - */ - public static boolean delHash(final String key, final String field) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - try { - // 计数器 - int count = 2; - - // 自动处理 key - String cacheKey = CacheUtil.handleKey(CacheType.EDEN_HASH, key); - - // 删除 EhCache - boolean ehcacheRet = ehCachePlugin.delete(CacheConstants.EHCACHE_SPACE,cacheKey +":"+ field); - if(ehcacheRet){ - count--; - } - - // 删除 Redis - Long hDeleteLong = redisPlugin.hDelete(cacheKey, field); - if(hDeleteLong != null && hDeleteLong > 0){ - count--; - } - - return count == 0; - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return false; - } - - // ==================================================================== - - /** - * 放一个空属性 有效时间为 5分钟 - * 用于 防止穿透判断 弥补布隆过滤器 - * - * @param key 键 - * @return boolean - */ - public static boolean putNilFlag(String key) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - // 处理缓存 key - String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + ":" + key); - - try { - // 存入Redis - Long increment = redisPlugin.increment(cacheKey); - // 设置失效时间 - redisPlugin.expire(cacheKey, TTL_NIL_DATA_TIME); - return increment != null; - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return false; - } - - /** - * 删除空属性 - * 用于 防止穿透判断 弥补布隆过滤器 - * - * @param key 键 - * @return boolean - */ - public static boolean delNilFlag(String key) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 处理缓存 key - String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + ":" + key); - try { - // 删除Redis - return redisPlugin.del(cacheKey); - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return false; - } - - - /** - * 获得一个空属性 有效时间为 5分钟 - * 用于 防止穿透判断 弥补布隆过滤器 - * - * @param key 键 - * @return boolean - */ - public static boolean hasNilFlag(String key) { - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - // 处理缓存 key - String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + ":" + key); - - try { - Object nilObj = redisPlugin.get(cacheKey); - if(nilObj == null){ - return false; - } - - Long nilNum = Convert.toLong(nilObj, 0L); - return NIL_FLAG_THRESHOLD < nilNum; - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return false; - } - - - // ==================================================================== - - /** - * 处理 key 默认为临时 - * @param key 缓存Key - * @return String - */ - public static String handleKey(String key){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - return CacheUtil.handleKey(CacheType.TIMED, key); - } - - /** - * 处理 key - * @param cacheType 缓存类型 - * @param key 缓存Key - * @return String - */ - public static String handleKey(CacheType cacheType, String key){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - return PREFIX_NAME + cacheType.getName() + ":" + - key; - } /** * 格式化Key @@ -754,74 +61,12 @@ public class CacheUtil { } - /** - * 内部处理 普通 key - * @param key 缓存Key - * @param isEden 是否永久 - * @return String - */ - private static String handleUsualKey(String key, boolean isEden){ - if(isEden){ - return CacheUtil.handleKey(CacheType.EDEN, key); - } - return CacheUtil.handleKey(CacheType.TIMED, key); - } - - /** - * 读配置文件 - */ - private static void readPropertyXML() throws IOException { - // 有坑 读 xml - ClassPathResource resource = new ClassPathResource("config/ehcache-opsli.xml"); - Document document = XmlUtil.readXML(resource.getInputStream()); - NodeList nodeList = document.getElementsByTagName("cache"); - if(nodeList != null){ - for (int i = 0; i < nodeList.getLength(); i++) { - Node item = nodeList.item(i); - NamedNodeMap attributes = item.getAttributes(); - if(attributes == null){ - continue; - } - Node alias = attributes.getNamedItem("alias"); - if("hotData".equals(alias.getNodeValue())){ - NodeList childNodes = item.getChildNodes(); - if(childNodes != null){ - for (int j = 0; j < childNodes.getLength(); j++) { - if("expiry".equals(childNodes.item(j).getNodeName())){ - NodeList expiryNodes = childNodes.item(j).getChildNodes(); - if(expiryNodes != null){ - for (int k = 0; k < expiryNodes.getLength(); k++) { - if("ttl".equals(expiryNodes.item(k).getNodeName())){ - Node ttlNode = expiryNodes.item(k); - Node ttlValue = ttlNode.getFirstChild(); - // 默认 60000秒 6小时 - TTL_HOT_DATA_TIME = Convert.toInt(ttlValue.getNodeValue(), 21600); - break; - } - } - } - break; - } - } - } - break; - } - } - } - } - /** * 初始化 */ @Autowired - public void init(CacheProperties cacheProperties, - RedisPlugin redisPlugin, - EhCachePlugin ehCachePlugin){ - - CacheUtil.PREFIX_NAME = Convert.toStr(cacheProperties.getPrefix(), "opsli") + ":"; - CacheUtil.redisPlugin = redisPlugin; - CacheUtil.ehCachePlugin = ehCachePlugin; - + public void init(CacheProperties cacheProperties){ + CacheUtil.PREFIX_NAME = Convert.toStr(cacheProperties.getPrefix(), "opsli"); IS_INIT = true; } diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/SecurityCache.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/SecurityCache.java index e9111bf6..a7f9616e 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/SecurityCache.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/cache/SecurityCache.java @@ -1,8 +1,24 @@ +/** + * 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; import cn.hutool.core.convert.Convert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.util.concurrent.Striped; @@ -144,10 +160,12 @@ public final class SecurityCache { throw new RuntimeException("入参[redisTemplate,key,val]必填"); } + String cacheKey = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV); + // 判断是否为永久存储 if(isEden) { redisTemplate.opsForValue() - .set("kv#" + key, val); + .set(cacheKey, val); }else{ // 随机缓存失效时间 防止缓存雪崩 // 范围在当前时效的 1.2 - 2倍 @@ -159,7 +177,12 @@ public final class SecurityCache { ); redisTemplate.opsForValue() - .set(CACHE_PREFIX_KV + key, val, timeout, TimeUnit.SECONDS); + .set( + cacheKey, + val, + timeout, + TimeUnit.SECONDS + ); } // 清除本地记录 @@ -356,8 +379,10 @@ public final class SecurityCache { throw new RuntimeException("入参[redisTemplate,key,cacheMap]必填"); } + String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH); + redisTemplate.opsForHash() - .putAll(CACHE_PREFIX_HASH + key, cacheMap); + .putAll(cacheKeyByHash, cacheMap); // 清除本地记录 LFU_NULL_CACHE.invalidate(key); @@ -378,8 +403,10 @@ public final class SecurityCache { throw new RuntimeException("入参[redisTemplate,key,field,val]必填"); } + String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH); + redisTemplate.opsForHash() - .put(CACHE_PREFIX_HASH + key, field, val); + .put(cacheKeyByHash, field, val); final String tempKey = key + "_" + field; // 清除本地记录 @@ -431,8 +458,13 @@ public final class SecurityCache { // 清除本地记录 LFU_NULL_CACHE.invalidate(key); + + String cacheKeyByKv = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV); + String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH); + // 清除缓存 - redisTemplate.delete(key); + redisTemplate.delete(cacheKeyByKv); + redisTemplate.delete(cacheKeyByHash); return true; } @@ -455,8 +487,10 @@ public final class SecurityCache { return null; } + String cacheKey = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_KV); + // 从 缓存回调查询数据 - cache = redisTemplate.opsForValue().get(CACHE_PREFIX_KV + key); + cache = redisTemplate.opsForValue().get(cacheKey); }catch (Exception e){ log.error(e.getMessage(), e); } @@ -481,8 +515,10 @@ public final class SecurityCache { return null; } + String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH); + // 从 缓存回调查询数据 - cache = redisTemplate.opsForHash().get(CACHE_PREFIX_HASH + key, field); + cache = redisTemplate.opsForHash().get(cacheKeyByHash, field); }catch (Exception e){ log.error(e.getMessage(), e); } @@ -508,8 +544,10 @@ public final class SecurityCache { return null; } + String cacheKeyByHash = StrUtil.addPrefixIfNot(key, CACHE_PREFIX_HASH); + // 从 缓存回调查询数据 - Map entries = redisTemplate.opsForHash().entries(CACHE_PREFIX_HASH + key); + Map entries = redisTemplate.opsForHash().entries(cacheKeyByHash); // 如果补偿器不为空 则进行补偿判断 if(null != callbackSourceCount){ diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/filters/aspect/CacheDataAop.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/filters/aspect/CacheDataAop.java deleted file mode 100644 index d5bbf7f4..00000000 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/filters/aspect/CacheDataAop.java +++ /dev/null @@ -1,299 +0,0 @@ -/** - * 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.filters.aspect; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.convert.Convert; -import com.google.common.collect.Lists; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.opsli.api.base.warpper.ApiWrapper; -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.core.cache.CacheUtil; -import org.opsli.core.cache.pushsub.entity.CacheDataEntity; -import org.opsli.core.cache.pushsub.enums.CacheHandleType; -import org.opsli.core.cache.pushsub.msgs.CacheDataMsgFactory; -import org.opsli.plugins.redis.RedisPlugin; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.List; - -import static org.opsli.common.constants.OrderConstants.HOT_DATA_ORDER; - -/** - * 热点数据 拦截处理 - * - * @author parker - * @date 2020-09-16 - */ -@Slf4j -@Order(HOT_DATA_ORDER) -@Aspect -@Component -public class CacheDataAop { - - @Autowired - private RedisPlugin redisPlugin; - - @Pointcut("@annotation(org.opsli.common.annotation.hotdata.HotDataPut)") - public void hotDataPut() { - } - - @Pointcut("@annotation(org.opsli.common.annotation.hotdata.HotDataDel)") - public void hotDataDel() { - } - - /** - * 切如 更新数据 - * @param point point - * @return Object - * @throws Throwable 异常 - */ - @Around("hotDataPut()") - public Object hotDataPutProcess(ProceedingJoinPoint point) throws Throwable { - Object[] args = point.getArgs(); - Object returnValue = point.proceed(args); - // 判断 方法上是否使用 EnableHotData注解 如果没有表示开启热数据 则直接跳过 - Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class); - if(annotation == null){ - return returnValue; - } - - List cacheDataEntityList = this.putHandlerData(point, returnValue); - // 非法判断 - if(CollUtil.isEmpty(cacheDataEntityList)){ - return returnValue; - } - - for (CacheDataEntity cacheDataEntity : cacheDataEntityList) { - // 更新缓存数据 - // 热点数据 - boolean putRet = CacheUtil.put(CacheConstants.HOT_DATA_PREFIX +":"+ cacheDataEntity.getKey(), - returnValue); - if(putRet){ - // 广播缓存数据 - 通知其他服务器同步数据 - redisPlugin.sendMessage( - CacheDataMsgFactory.createMsg( - cacheDataEntity, returnValue, CacheHandleType.UPDATE) - ); - } - } - - return returnValue; - } - - - /** - * 切如 删除数据 和 逻辑删除上 - * @param point point - * @return Object - * @throws Throwable 异常 - */ - @Around("hotDataDel()") - public Object hotDataDelProcess(ProceedingJoinPoint point) throws Throwable { - Object[] args= point.getArgs(); - Object returnValue = point.proceed(args); - // 判断 方法上是否使用 EnableHotData注解 如果没有表示开启热数据 则直接跳过 - Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class); - if(annotation == null){ - return returnValue; - } - - // 删除状态判断 - try { - Boolean ret = (Boolean) returnValue; - if(ret == null || !ret){ - return returnValue; - } - }catch (Exception e){ - log.error(e.getMessage(),e); - return returnValue; - } - - List cacheDataEntityList = this.delHandlerData(point, args); - // 非法判断 - if(CollUtil.isEmpty(cacheDataEntityList)){ - return returnValue; - } - - for (CacheDataEntity cacheDataEntity : cacheDataEntityList) { - // 更新缓存数据 - 删除缓存 - boolean delRet = CacheUtil.del(CacheConstants.HOT_DATA_PREFIX +":"+ cacheDataEntity.getKey()); - if(delRet){ - // 广播缓存数据 - 通知其他服务器同步数据 - redisPlugin.sendMessage( - CacheDataMsgFactory.createMsg( - cacheDataEntity, null, CacheHandleType.DELETE) - ); - } - } - - return returnValue; - } - - - // =========================================================================== - - - /*** - * PUT 处理数据 - * @param point point - */ - private List putHandlerData(ProceedingJoinPoint point, Object returnValue){ - // 这里 只对 继承了 ApiWrapper 的类做处理 - if(!(returnValue instanceof ApiWrapper)){ - return null; - } - - // 消息集合 后续可能会考虑 多消息存储 - List cacheDataEntities = Lists.newArrayListWithCapacity(1); - - // 报错不处理 - try { - // 获得方法 - Method objMethod = this.getMethod(point); - if(objMethod == null) { - return null; - } - - // 获取注解参数 - HotDataPut aCache = objMethod.getAnnotation(HotDataPut.class); - if(aCache != null){ - // 这里 只对 继承了 BaseEntity 的类做处理 - ApiWrapper apiWrapper = (ApiWrapper) returnValue; - - CacheDataEntity ret = new CacheDataEntity(apiWrapper.getId()); - // 存放数据 - this.putCacheData(cacheDataEntities, ret); - - return cacheDataEntities; - } - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return null; - } - - - /*** - * DEL 处理数据 - * @param point point - */ - private List delHandlerData(ProceedingJoinPoint point, Object[] args){ - if(args == null || args.length == 0){ - return null; - } - - // 消息集合 - List cacheDataEntities = Lists.newArrayListWithCapacity(args.length); - - // 报错不处理 - try { - // 获得方法 - Method objMethod = this.getMethod(point); - if(objMethod == null) { - return null; - } - - // 获取注解参数 - HotDataDel aCache= objMethod.getAnnotation(HotDataDel.class); - if(aCache != null){ - - List keyList = null; - - // 处理数据 - for (Object arg : args) { - if (arg instanceof ApiWrapper) { - // key 存储ID - ApiWrapper apiWrapper = Convert.convert(ApiWrapper.class, arg); - keyList = Convert.toList(String.class, apiWrapper.getId()); - } else if (arg instanceof Collection) { - try { - keyList = Lists.newArrayList(); - List baseEntityList = Convert.toList(ApiWrapper.class, arg); - for (ApiWrapper baseEntity : baseEntityList) { - keyList.add(baseEntity.getId()); - } - }catch (Exception e){ - log.error(e.getMessage(),e); - } - }else { - keyList = Convert.toList(String.class, arg); - } - } - - if(keyList != null && CollUtil.isNotEmpty(keyList)){ - for (String key : keyList) { - CacheDataEntity ret = new CacheDataEntity(key); - // 存放数据 - this.putCacheData(cacheDataEntities, ret); - } - } - - return cacheDataEntities; - } - }catch (Exception e){ - log.error(e.getMessage(),e); - } - return null; - } - - - // ===================== - - /** - * 获得方法 - * @param point point - * @return Method 方法 - */ - 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(cacheDataList == null){ - return; - } - cacheDataList.add(cacheData); - } - - -} 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 23ea767f..c06a581e 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 @@ -98,8 +98,11 @@ public class CaptchaUtil { // 生成验证码 Captcha captcha = captchaStrategy.createCaptcha(); + // 缓存Key + String cacheKey = CacheUtil.formatKey(PREFIX + uuid); + // 保存至缓存 - boolean ret = redisPlugin.put(CacheUtil.getPrefixName() + PREFIX + uuid, captcha.text(), TIME_OUT); + boolean ret = redisPlugin.put(cacheKey, captcha.text(), TIME_OUT); if(ret){ // 输出 captcha.out(out); @@ -127,8 +130,11 @@ public class CaptchaUtil { throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_CODE_NULL); } + // 缓存Key + String cacheKey = CacheUtil.formatKey(PREFIX + uuid); + // 验证码 - String codeTemp = (String) redisPlugin.get(CacheUtil.getPrefixName() + PREFIX + uuid); + String codeTemp = (String) redisPlugin.get(cacheKey); if (StringUtils.isEmpty(codeTemp)) { throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_NULL); } @@ -156,8 +162,11 @@ public class CaptchaUtil { return false; } + // 缓存Key + String cacheKey = CacheUtil.formatKey(PREFIX + uuid); + //删除验证码 - return redisPlugin.del(CacheUtil.getPrefixName() + PREFIX + uuid); + return redisPlugin.del(cacheKey); } // ====================== diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/DistributedLockUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/DistributedLockUtil.java index 2fcd5999..4ad19619 100644 --- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/DistributedLockUtil.java +++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/DistributedLockUtil.java @@ -60,7 +60,9 @@ public class DistributedLockUtil { boolean isLock = true; // 分布式上锁 if(REDISSON_LOCK != null){ - isLock = REDISSON_LOCK.tryLock(CacheUtil.getPrefixName() + lockName, LEASE_TIME); + // 缓存Key + String cacheKey = CacheUtil.formatKey(lockName); + isLock = REDISSON_LOCK.tryLock(cacheKey, LEASE_TIME); } return isLock; } @@ -76,7 +78,9 @@ public class DistributedLockUtil { // 释放锁 if(REDISSON_LOCK != null){ - REDISSON_LOCK.unlockByThread(CacheUtil.getPrefixName() + lockName); + // 缓存Key + String cacheKey = CacheUtil.formatKey(lockName); + REDISSON_LOCK.unlockByThread(cacheKey); } } 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 2f710acb..b6bc8f91 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 @@ -45,9 +45,6 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER; @Lazy(false) public class MenuUtil { - /** 前缀 */ - public static final String PREFIX_CODE = "menu:code:"; - /** 菜单 Api */ private static MenuApi menuApi; 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 fca7063a..c6a6e865 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 @@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.opsli.api.base.result.ResultVo; import org.opsli.api.wrapper.system.user.UserModel; +import org.opsli.common.constants.RedisConstants; import org.opsli.common.constants.SignConstants; import org.opsli.common.constants.TokenConstants; import org.opsli.common.constants.TokenTypeConstants; @@ -64,12 +65,6 @@ public class UserTokenUtil { /** token 缓存名 */ public static final String TOKEN_NAME = TokenConstants.ACCESS_TOKEN; - /** 缓存前缀 */ - private static final String TICKET_PREFIX = "ticket:"; - /** 账号失败次数 */ - public static final String ACCOUNT_SLIP_COUNT_PREFIX = "account:slip:count:"; - /** 账号失败锁定KEY */ - public static final String ACCOUNT_SLIP_LOCK_PREFIX = "account:slip:lock:"; /** 限制登录数量 -1 为无限大 */ public static final int ACCOUNT_LIMIT_INFINITE = -1; /** 登录配置信息 */ @@ -100,8 +95,8 @@ public class UserTokenUtil { // 如果当前登录开启 数量限制 if(LOGIN_PROPERTIES.getLimitCount() > ACCOUNT_LIMIT_INFINITE){ // 当前用户已存在 Token数量 - Long ticketLen = redisPlugin.sSize(CacheUtil.getPrefixName() + - TICKET_PREFIX + user.getUsername()); + Long ticketLen = redisPlugin.sSize( + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + user.getUsername())); if(ticketLen !=null && ticketLen >= LOGIN_PROPERTIES.getLimitCount()){ // 如果是拒绝后者 则直接抛出异常 if(LoginLimitRefuse.AFTER == LOGIN_PROPERTIES.getLimitRefuse()){ @@ -110,7 +105,9 @@ public class UserTokenUtil { } // 如果是拒绝前者 则弹出前者 else { - redisPlugin.sPop(CacheUtil.getPrefixName() + TICKET_PREFIX + user.getUsername()); + redisPlugin.sPop( + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + user.getUsername()) + ); } } } @@ -135,11 +132,13 @@ public class UserTokenUtil { // 在redis存一份 token 是为了防止 人为造假 // 保存用户token Long saveLong = redisPlugin.sPut( - CacheUtil.getPrefixName() + TICKET_PREFIX + user.getUsername(), signToken); + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + user.getUsername()), + signToken + ); if(saveLong != null && saveLong > 0){ // 设置该用户全部token失效时间, 如果这时又有新设备登录 则续命 redisPlugin.expire( - CacheUtil.getPrefixName() + TICKET_PREFIX + user.getUsername(), + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + user.getUsername()), JwtUtil.EXPIRE_MILLISECOND, TimeUnit.MILLISECONDS); TokenRet tokenRet = new TokenRet(); @@ -249,11 +248,13 @@ public class UserTokenUtil { if(user != null){ // 删除Token信息 redisPlugin.sRemove( - CacheUtil.getPrefixName() + TICKET_PREFIX + user.getUsername(), token); + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + user.getUsername()), + token); // 如果缓存中 无该用户任何Token信息 则删除用户缓存 Long size = redisPlugin.sSize( - CacheUtil.getPrefixName() + TICKET_PREFIX + user.getUsername()); + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + user.getUsername()) + ); if(size == null || size == 0L) { // 删除相关信息 UserUtil.refreshUser(user); @@ -296,7 +297,8 @@ public class UserTokenUtil { String username = getUserNameByToken(token); boolean hashKey = redisPlugin.sHashKey( - CacheUtil.getPrefixName() + TICKET_PREFIX + username, token); + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + username), + token); if(!hashKey){ return false; } @@ -305,7 +307,7 @@ public class UserTokenUtil { if(BooleanUtil.isTrue(LOGIN_PROPERTIES.getReviveMode())){ // 设置该用户全部token失效时间, 如果这时又有新设备登录 则续命 redisPlugin.expire( - CacheUtil.getPrefixName() + TICKET_PREFIX + username, + CacheUtil.formatKey(RedisConstants.PREFIX_TICKET + username), JwtUtil.EXPIRE_MILLISECOND, TimeUnit.MILLISECONDS); } @@ -329,7 +331,7 @@ public class UserTokenUtil { // 判断账号是否临时锁定 Long loseTimeMillis = (Long) redisPlugin.get( - CacheUtil.getPrefixName() + ACCOUNT_SLIP_LOCK_PREFIX + username); + CacheUtil.formatKey(RedisConstants.PREFIX_ACCOUNT_SLIP_LOCK + username)); if(loseTimeMillis != null){ Date currDate = DateUtil.date(); DateTime loseDate = DateUtil.date(loseTimeMillis); @@ -364,18 +366,19 @@ public class UserTokenUtil { // 如果失败次数 超过阈值 则锁定账号 Long slipNum = redisPlugin.increment( - CacheUtil.getPrefixName() + ACCOUNT_SLIP_COUNT_PREFIX + username); + CacheUtil.formatKey(RedisConstants.PREFIX_ACCOUNT_SLIP_COUNT + username)); if (slipNum != null){ // 设置失效时间为 5分钟 redisPlugin.expire( - CacheUtil.getPrefixName() + ACCOUNT_SLIP_COUNT_PREFIX + username, LOGIN_PROPERTIES.getSlipLockSpeed()); + CacheUtil.formatKey(RedisConstants.PREFIX_ACCOUNT_SLIP_COUNT + username), + LOGIN_PROPERTIES.getSlipLockSpeed()); // 如果确认 都失败 则存入临时缓存 if(slipNum >= LOGIN_PROPERTIES.getSlipCount()){ long currentTimeMillis = System.currentTimeMillis(); // 存入Redis redisPlugin.put( - CacheUtil.getPrefixName() + ACCOUNT_SLIP_LOCK_PREFIX + username, + CacheUtil.formatKey(RedisConstants.PREFIX_ACCOUNT_SLIP_LOCK + username), currentTimeMillis, LOGIN_PROPERTIES.getSlipLockSpeed()); } } @@ -396,7 +399,7 @@ public class UserTokenUtil { long count = 0L; Object obj = redisPlugin.get( - CacheUtil.getPrefixName() + ACCOUNT_SLIP_COUNT_PREFIX + username); + CacheUtil.formatKey(RedisConstants.PREFIX_ACCOUNT_SLIP_COUNT + username)); if(obj != null){ try { count = Convert.convert(Long.class, obj); @@ -418,10 +421,10 @@ public class UserTokenUtil { // 删除失败次数记录 redisPlugin.del( - CacheUtil.getPrefixName() + ACCOUNT_SLIP_COUNT_PREFIX + username); + CacheUtil.formatKey(RedisConstants.PREFIX_ACCOUNT_SLIP_COUNT + username)); // 删除失败次数记录 redisPlugin.del( - CacheUtil.getPrefixName() + ACCOUNT_SLIP_LOCK_PREFIX + username); + CacheUtil.formatKey(RedisConstants.PREFIX_ACCOUNT_SLIP_LOCK + username)); } 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 471123cb..ca9aa1fa 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,16 +29,18 @@ import org.opsli.api.wrapper.system.menu.MenuModel; import org.opsli.api.wrapper.system.role.RoleModel; import org.opsli.api.wrapper.system.user.UserModel; import org.opsli.api.wrapper.system.user.UserOrgRefModel; -import org.opsli.api.wrapper.system.user.UserOrgRefWebModel; +import org.opsli.common.constants.RedisConstants; import org.opsli.common.exception.TokenException; import org.opsli.core.api.TokenThreadLocal; import org.opsli.core.autoconfigure.properties.GlobalProperties; import org.opsli.core.cache.CacheUtil; +import org.opsli.core.cache.SecurityCache; import org.opsli.core.msg.CoreMsg; import org.opsli.core.msg.TokenMsg; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.core.annotation.Order; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.List; @@ -57,16 +59,6 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER; @Lazy(false) public class UserUtil { - /** 前缀 */ - public static final String PREFIX_ID = "userId:"; - public static final String PREFIX_ID_ROLES = "userId:roles:"; - public static final String PREFIX_ID_DEF_ROLE = "userId:def_role:"; - public static final String PREFIX_ID_ORGS = "userId:orgs:"; - public static final String PREFIX_ID_DEF_ORG = "userId:def_org:"; - public static final String PREFIX_ID_PERMISSIONS = "userId:permissions:"; - public static final String PREFIX_ID_MENUS = "userId:menus:"; - public static final String PREFIX_USERNAME = "username:"; - /** 修改租户权限 */ private static final String PERMS_TENANT = "system_user_tenant"; @@ -85,6 +77,8 @@ public class UserUtil { /** 增加初始状态开关 防止异常使用 */ private static boolean IS_INIT; + private static RedisTemplate redisTemplate; + /** * 获得当前系统登陆用户 * @return UserModel @@ -169,67 +163,24 @@ public class UserUtil { CoreMsg.OTHER_EXCEPTION_UTILS_INIT); // 缓存Key - String cacheKey = PREFIX_ID + userId; - - // 先从缓存里拿 - UserModel userModel = CacheUtil.getTimed(UserModel.class, cacheKey); - if (userModel != null){ - // 如果不是递归触发 可进入一次 - if(!isRecursion){ - // 如果是 切换租户权限 则进行新一轮判断 - // 注意不要陷入递归死循环 只保障循环一次 - if (StringUtils.isNotBlank(userModel.getSwitchTenantUserId())){ - userModel = getUser(userModel.getSwitchTenantUserId(), true); - } - } - return userModel; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return null; - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return null; - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - userModel = CacheUtil.getTimed(UserModel.class, cacheKey); - if (userModel != null){ - return userModel; - } + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID + userId); + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 UserModel userModelTemp = new UserModel(); userModelTemp.setId(userId); // 设置为系统内部调用 否则 会拿到 空值 userModelTemp.setIzApi(true); + + // 查询数据库 ResultVo resultVo = userApi.get(userModelTemp); - if(resultVo.isSuccess()){ - userModel = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, userModel); + if(!resultVo.isSuccess()){ + return null; } + return resultVo.getData(); + }, true); - }catch (Exception e){ - log.error(e.getMessage(), e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } - - if(userModel == null){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); - return null; - } + UserModel userModel = Convert.convert(UserModel.class, cache); // 如果不是递归触发 可进入一次 if(!isRecursion){ @@ -255,56 +206,18 @@ public class UserUtil { CoreMsg.OTHER_EXCEPTION_UTILS_INIT); // 缓存Key - String cacheKey = PREFIX_USERNAME + userName; - - // 先从缓存里拿 - UserModel userModel = CacheUtil.getTimed(UserModel.class, cacheKey); - if (userModel != null){ - return userModel; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return null; - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return null; - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - userModel = CacheUtil.getTimed(UserModel.class, cacheKey); - if (userModel != null) { - return userModel; - } + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USERNAME + userName); + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 ResultVo resultVo = userApi.getUserByUsername(userName); - if (resultVo.isSuccess()) { - userModel = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, userModel); + if(!resultVo.isSuccess()){ + return null; } - }catch (Exception e){ - log.error(e.getMessage(), e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } + return resultVo.getData(); + }, true); - if(userModel == null){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); - return null; - } - - return userModel; + return Convert.convert(UserModel.class, cache); } /** @@ -325,59 +238,22 @@ public class UserUtil { } // 缓存Key - String cacheKey = PREFIX_ID_ROLES + userId; - - List roles; - - // 先从缓存里拿 - Object obj = CacheUtil.getTimed(cacheKey); - roles = Convert.toList(String.class, obj); - if(CollUtil.isNotEmpty(roles)){ - return roles; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return ListUtil.empty(); - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return ListUtil.empty(); - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - obj = CacheUtil.getTimed(cacheKey); - roles = Convert.toList(String.class, obj); - if(CollUtil.isNotEmpty(roles)){ - return roles; - } + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_AND_ROLES + userId); + final String finalUserId = userId; + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 - ResultVo> resultVo = userRoleRefApi.getRolesByUserId(userId); - if(resultVo.isSuccess()){ - roles = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, roles); + ResultVo> resultVo = userRoleRefApi.getRolesByUserId(finalUserId); + if(!resultVo.isSuccess()){ + return null; } - }catch (Exception e){ - log.error(e.getMessage(), e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } + return resultVo.getData(); + }, true); - if(CollUtil.isEmpty(roles)){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); + List roles = Convert.toList(String.class, cache); + if(null == roles){ return ListUtil.empty(); } - return roles; } @@ -399,60 +275,24 @@ public class UserUtil { userId = currUser.getSwitchTenantUserId(); } - // 缓存Key - String cacheKey = PREFIX_ID_PERMISSIONS + userId; - - List permissions; - - // 先从缓存里拿 - Object obj = CacheUtil.getTimed(cacheKey); - permissions = Convert.toList(String.class, obj); - if(CollUtil.isNotEmpty(permissions)){ - return permissions; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return ListUtil.empty(); - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return ListUtil.empty(); - } - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - obj = CacheUtil.getTimed(cacheKey); - permissions = Convert.toList(String.class, obj); - if(CollUtil.isNotEmpty(permissions)){ - return permissions; - } + // 缓存Key + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_PERMISSIONS + userId); + final String finalUserId = userId; + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 - ResultVo> resultVo = userRoleRefApi.getAllPerms(userId); - if(resultVo.isSuccess()){ - permissions = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, permissions); + ResultVo> resultVo = userRoleRefApi.getAllPerms(finalUserId); + if(!resultVo.isSuccess()){ + return null; } - }catch (Exception e){ - log.error(e.getMessage(), e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } + return resultVo.getData(); + }, true); - if(CollUtil.isEmpty(permissions)){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); + List permissions = Convert.toList(String.class, cache); + if(null == permissions){ return ListUtil.empty(); } - return permissions; } @@ -473,61 +313,24 @@ public class UserUtil { userId = currUser.getSwitchTenantUserId(); } - // 缓存Key - String cacheKey = PREFIX_ID_ORGS + userId; - - List orgList; - - // 先从缓存里拿 - Object obj = CacheUtil.getTimed(cacheKey); - orgList = Convert.toList(UserOrgRefModel.class, obj); - if(CollUtil.isNotEmpty(orgList)){ - return orgList; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return ListUtil.empty(); - } + // 缓存Key + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_ORGS + userId); - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return ListUtil.empty(); - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - obj = CacheUtil.getTimed(cacheKey); - orgList = Convert.toList(UserOrgRefModel.class, obj); - if(CollUtil.isNotEmpty(orgList)){ - return orgList; - } - + final String finalUserId = userId; + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 - ResultVo> resultVo = userOrgRefApi.findListByUserId(userId); - if(resultVo.isSuccess()){ - orgList = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, orgList); + ResultVo> resultVo = userOrgRefApi.findListByUserId(finalUserId); + if(!resultVo.isSuccess()){ + return null; } - }catch (Exception e){ - log.error(e.getMessage(), e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } + return resultVo.getData(); + }, true); - if(CollUtil.isEmpty(orgList)){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); + List orgList = Convert.toList(UserOrgRefModel.class, cache); + if(null == orgList){ return ListUtil.empty(); } - return orgList; } @@ -561,61 +364,24 @@ public class UserUtil { userId = currUser.getSwitchTenantUserId(); } - // 缓存Key - String cacheKey = PREFIX_ID_MENUS + userId; - - List menus; - - // 先从缓存里拿 - Object obj = CacheUtil.getTimed(cacheKey); - menus = Convert.toList(MenuModel.class, obj); - if(CollUtil.isNotEmpty(menus)){ - return menus; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return ListUtil.empty(); - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return ListUtil.empty(); - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - obj = CacheUtil.getTimed(cacheKey); - menus = Convert.toList(MenuModel.class, obj); - if(CollUtil.isNotEmpty(menus)){ - return menus; - } + // 缓存Key + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_MENUS + userId); + final String finalUserId = userId; + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 - ResultVo> resultVo = userRoleRefApi.getMenuListByUserId(userId); - if(resultVo.isSuccess()){ - menus = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, menus); + ResultVo> resultVo = userRoleRefApi.getMenuListByUserId(finalUserId); + if(!resultVo.isSuccess()){ + return null; } - }catch (Exception e){ - log.error(e.getMessage(), e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } + return resultVo.getData(); + }, true); - if(CollUtil.isEmpty(menus)){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); + List menus = Convert.toList(MenuModel.class, cache); + if(null == menus){ return ListUtil.empty(); } - return menus; } @@ -637,57 +403,21 @@ public class UserUtil { userId = currUser.getSwitchTenantUserId(); } - // 缓存Key - String cacheKey = PREFIX_ID_DEF_ROLE + userId; - - // 先从缓存里拿 - RoleModel roleModel = CacheUtil.getTimed(RoleModel.class, cacheKey); - if (roleModel != null){ - return roleModel; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return null; - } - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return null; - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - roleModel = CacheUtil.getTimed(RoleModel.class, cacheKey); - if (roleModel != null){ - return roleModel; - } + // 缓存Key + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_DEF_ROLE + userId); + final String finalUserId = userId; + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 - ResultVo resultVo = userRoleRefApi.getDefRoleByUserId(userId); - if(resultVo.isSuccess()){ - roleModel = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, roleModel); + ResultVo resultVo = userRoleRefApi.getDefRoleByUserId(finalUserId); + if(!resultVo.isSuccess()){ + return null; } - }catch (Exception e){ - log.error(e.getMessage(),e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } - - if(roleModel == null){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); - return null; - } + return resultVo.getData(); + }, true); - return roleModel; + return Convert.convert(RoleModel.class, cache); } @@ -710,56 +440,19 @@ public class UserUtil { } // 缓存Key - String cacheKey = PREFIX_ID_DEF_ORG + userId; - - // 先从缓存里拿 - UserOrgRefModel orgModel = CacheUtil.getTimed(UserOrgRefModel.class, cacheKey); - if (orgModel != null){ - return orgModel; - } - - // 拿不到 -------- - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return null; - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return null; - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - orgModel = CacheUtil.getTimed(UserOrgRefModel.class, cacheKey); - if (orgModel != null){ - return orgModel; - } + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_DEF_ORG + userId); + final String finalUserId = userId; + Object cache = SecurityCache.get(redisTemplate, cacheKey, (k) -> { // 查询数据库 - ResultVo resultVo = userOrgRefApi.getDefOrgByUserId(userId); - if(resultVo.isSuccess()){ - orgModel = resultVo.getData(); - // 存入缓存 - CacheUtil.put(cacheKey, orgModel); + ResultVo resultVo = userOrgRefApi.getDefOrgByUserId(finalUserId); + if(!resultVo.isSuccess()){ + return null; } - }catch (Exception e){ - log.error(e.getMessage(),e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } - - if(orgModel == null){ - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); - return null; - } + return resultVo.getData(); + }, true); - return orgModel; + return Convert.convert(UserOrgRefModel.class, cache); } @@ -781,33 +474,11 @@ public class UserUtil { } // 缓存Key - String cacheKey = PREFIX_ID + user.getId(); - try { - // 存入缓存 - CacheUtil.put(cacheKey, user); - }catch (Exception e){ - log.error(e.getMessage(), e); - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return false; - } + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID + user.getId()); + // 存入缓存 + SecurityCache.put(redisTemplate, cacheKey, user); - // 存入缓存 - flag = CacheUtil.put(cacheKey, user); - }catch (Exception e){ - flag = false; - log.error(e.getMessage(), e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } - - return flag; + return true; } /** @@ -824,49 +495,22 @@ public class UserUtil { return true; } - UserModel userModelById = CacheUtil.getTimed( - UserModel.class, PREFIX_ID + user.getId()); - UserModel userModelByUsername = CacheUtil.getTimed( - UserModel.class, PREFIX_USERNAME + user.getUsername()); - - boolean hasNilFlagById = CacheUtil.hasNilFlag(PREFIX_ID + user.getId()); - boolean hasNilFlagByName = CacheUtil.hasNilFlag(PREFIX_USERNAME + user.getUsername()); + String cacheKeyByUserId = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID + user.getId()); + String cacheKeyByUsername = CacheUtil.formatKey(RedisConstants.PREFIX_USERNAME + user.getUsername()); // 计数器 - int count = 0; - - if (hasNilFlagById){ - count++; + int count = 2; + { // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_ID + user.getId()); + boolean tmp = SecurityCache.remove(redisTemplate, cacheKeyByUserId); if(tmp){ count--; } } - if (hasNilFlagByName){ - count++; + { // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_USERNAME + user.getUsername()); - if(tmp){ - count--; - } - } - - // 只要有一个不为空 则执行刷新 - if (userModelById != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_ID + user.getId()); - if(tmp){ - count--; - } - } - - if (userModelByUsername != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_USERNAME + user.getUsername()); + boolean tmp = SecurityCache.remove(redisTemplate, cacheKeyByUsername); if(tmp){ count--; } @@ -886,32 +530,9 @@ public class UserUtil { ThrowExceptionUtil.isThrowException(!IS_INIT, CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - Object obj = CacheUtil.getTimed(PREFIX_ID_ROLES + userId); - boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_ROLES + userId); + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_AND_ROLES + userId); - // 计数器 - int count = 0; - - // 只要不为空 则执行刷新 - if (hasNilFlag){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_ID_ROLES + userId); - if(tmp){ - count--; - } - } - - if(obj != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_ID_ROLES + userId); - if(tmp){ - count--; - } - } - - return count == 0; + return SecurityCache.remove(redisTemplate, cacheKey); } /** @@ -928,32 +549,9 @@ public class UserUtil { return true; } - // 计数器 - int count = 0; - - RoleModel roleModel = CacheUtil.getTimed(RoleModel.class, PREFIX_ID_DEF_ROLE + userId); - boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_DEF_ROLE + userId); + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_DEF_ROLE + userId); - // 只要不为空 则执行刷新 - if (hasNilFlag){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_ID_DEF_ROLE + userId); - if(tmp){ - count--; - } - } - - if(roleModel != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_ID_DEF_ROLE + userId); - if(tmp){ - count--; - } - } - - return count == 0; + return SecurityCache.remove(redisTemplate, cacheKey); } @@ -968,34 +566,9 @@ public class UserUtil { ThrowExceptionUtil.isThrowException(!IS_INIT, CoreMsg.OTHER_EXCEPTION_UTILS_INIT); + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_PERMISSIONS + userId); - Object obj = CacheUtil.getTimed(PREFIX_ID_PERMISSIONS + userId); - boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_PERMISSIONS + userId); - - // 计数器 - int count = 0; - - // 只要不为空 则执行刷新 - if (hasNilFlag){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_ID_PERMISSIONS + userId); - if(tmp){ - count--; - } - } - - if(obj != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_ID_PERMISSIONS + userId); - if(tmp){ - count--; - } - } - - - return count == 0; + return SecurityCache.remove(redisTemplate, cacheKey); } /** @@ -1012,31 +585,9 @@ public class UserUtil { return true; } - // 计数器 - int count = 0; - - UserOrgRefWebModel orgRefModel = CacheUtil.getTimed(UserOrgRefWebModel.class, PREFIX_ID_ORGS + userId); - boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_ORGS + userId); - - // 只要不为空 则执行刷新 - if (hasNilFlag){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_ID_ORGS + userId); - if(tmp){ - count--; - } - } + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_ORGS + userId); - if(orgRefModel != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_ID_ORGS + userId); - if(tmp){ - count--; - } - } - return count == 0; + return SecurityCache.remove(redisTemplate, cacheKey); } /** @@ -1053,32 +604,9 @@ public class UserUtil { return true; } - // 计数器 - int count = 0; - - UserOrgRefModel orgModel = CacheUtil.getTimed(UserOrgRefModel.class, PREFIX_ID_DEF_ORG + userId); - boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_DEF_ORG + userId); + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_DEF_ORG + userId); - // 只要不为空 则执行刷新 - if (hasNilFlag){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_ID_DEF_ORG + userId); - if(tmp){ - count--; - } - } - - if(orgModel != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_ID_DEF_ORG + userId); - if(tmp){ - count--; - } - } - - return count == 0; + return SecurityCache.remove(redisTemplate, cacheKey); } @@ -1092,33 +620,9 @@ public class UserUtil { ThrowExceptionUtil.isThrowException(!IS_INIT, CoreMsg.OTHER_EXCEPTION_UTILS_INIT); + String cacheKey = CacheUtil.formatKey(RedisConstants.PREFIX_USER_ID_MENUS + userId); - Object obj = CacheUtil.getTimed(PREFIX_ID_MENUS + userId); - boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_MENUS + userId); - - // 计数器 - int count = 0; - - // 只要不为空 则执行刷新 - if (hasNilFlag){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(PREFIX_ID_MENUS + userId); - if(tmp){ - count--; - } - } - - if(obj != null){ - count++; - // 先删除 - boolean tmp = CacheUtil.del(PREFIX_ID_MENUS + userId); - if(tmp){ - count--; - } - } - - return count == 0; + return SecurityCache.remove(redisTemplate, cacheKey); } /** @@ -1201,7 +705,8 @@ public class UserUtil { public void init(GlobalProperties globalProperties, UserApi userApi, UserRoleRefApi userRoleRefApi, - UserOrgRefApi userOrgRefApi){ + UserOrgRefApi userOrgRefApi, + RedisTemplate redisTemplate) { if(globalProperties != null && globalProperties.getAuth() != null && globalProperties.getAuth().getToken() != null ){ @@ -1210,11 +715,9 @@ public class UserUtil { } UserUtil.userApi = userApi; - UserUtil.userRoleRefApi = userRoleRefApi; - UserUtil.userOrgRefApi = userOrgRefApi; - + UserUtil.redisTemplate = redisTemplate; IS_INIT = true; } diff --git a/opsli-modulars/opsli-modulars-generator/src/main/java/org/opsli/plugins/generator/utils/GenTemplateUtil.java b/opsli-modulars/opsli-modulars-generator/src/main/java/org/opsli/plugins/generator/utils/GenTemplateUtil.java index 826b1796..7868f839 100644 --- a/opsli-modulars/opsli-modulars-generator/src/main/java/org/opsli/plugins/generator/utils/GenTemplateUtil.java +++ b/opsli-modulars/opsli-modulars-generator/src/main/java/org/opsli/plugins/generator/utils/GenTemplateUtil.java @@ -20,16 +20,18 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.comparator.CompareUtil; import cn.hutool.core.convert.Convert; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; import org.opsli.core.cache.CacheUtil; +import org.opsli.core.cache.SecurityCache; import org.opsli.core.msg.CoreMsg; -import org.opsli.core.utils.DistributedLockUtil; import org.opsli.core.utils.ThrowExceptionUtil; import org.opsli.modulars.generator.template.service.IGenTemplateDetailService; import org.opsli.modulars.generator.template.wrapper.GenTemplateDetailModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.core.annotation.Order; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.List; @@ -53,11 +55,13 @@ public class GenTemplateUtil { private static boolean IS_INIT; /** 缓存前缀 NAME */ - private static final String CACHE_PREFIX_NAME = "gen:template:"; + private static final String CACHE_PREFIX_NAME = "hash#{}:gen:template:"; /** 代码模板明细 Service */ private static IGenTemplateDetailService genTemplateDetailService; + private static RedisTemplate redisTemplate; + /** * 根据模板ID 模板明细列表 * @param parentId 模板ID @@ -69,77 +73,21 @@ public class GenTemplateUtil { CoreMsg.OTHER_EXCEPTION_UTILS_INIT); // 缓存Key - String cacheKey = CACHE_PREFIX_NAME + parentId; - - // 处理集合数据 - List wrapperModels = handleDictList( - CacheUtil.getHashAll(cacheKey), parentId); - if(CollUtil.isNotEmpty(wrapperModels)){ - return sortWrappers(wrapperModels); - } - - // 防止缓存穿透判断 - boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey); - if(hasNilFlag){ - return sortWrappers(wrapperModels); - } - - try { - // 分布式加锁 - if(!DistributedLockUtil.lock(cacheKey)){ - // 无法申领分布式锁 - log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage()); - return sortWrappers(wrapperModels); - } - - // 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求 - // 处理集合数据 - wrapperModels = handleDictList( - CacheUtil.getHashAll(cacheKey), parentId); - if(CollUtil.isNotEmpty(wrapperModels)){ - return sortWrappers(wrapperModels); - } - + String cacheKey = CacheUtil.formatKey(CACHE_PREFIX_NAME + parentId); - List listByParent = genTemplateDetailService.findListByParent(parentId); + Map templateCache = SecurityCache.hGetAll(redisTemplate, cacheKey, (k) -> { // 处理数据库查询数据 - if(CollUtil.isNotEmpty(listByParent)){ - wrapperModels = listByParent; - // 计数器 - int count = wrapperModels.size(); - for (GenTemplateDetailModel model : wrapperModels) { - // 保存至缓存 - boolean ret = GenTemplateUtil.put(model); - if(ret){ - count--; - } - } - - // 回滚 清空缓存 - if(count != 0){ - for (GenTemplateDetailModel model : wrapperModels) { - GenTemplateUtil.del(model); - } - } - - return sortWrappers(wrapperModels); + List listByParent = genTemplateDetailService.findListByParent(parentId); + Map templateMap = Maps.newHashMapWithExpectedSize(listByParent.size()); + for (GenTemplateDetailModel genTemplateDetailModel : listByParent) { + templateMap.put(genTemplateDetailModel.getId(), genTemplateDetailModel); } + return templateMap; + }); - }catch (Exception e){ - log.error(e.getMessage(),e); - }finally { - // 释放锁 - DistributedLockUtil.unlock(cacheKey); - } - - // 如果值还是 为空 则赋默认值 - if(CollUtil.isEmpty(wrapperModels)){ - // 加入缓存防穿透 - // 设置空变量 用于防止穿透判断 - CacheUtil.putNilFlag(cacheKey); - } - // 排序 + // 处理集合数据 + List wrapperModels = handleDictList(templateCache); return sortWrappers(wrapperModels); } @@ -150,8 +98,8 @@ public class GenTemplateUtil { */ private static List sortWrappers(List wrapperModels) { // 非法判读 - if(wrapperModels == null){ - return null; + if(CollUtil.isEmpty(wrapperModels)){ + return ListUtil.empty(); } return ListUtil.sort(wrapperModels, @@ -162,22 +110,6 @@ public class GenTemplateUtil { // =============== - /** - * 删除 字典 - * @param model 字典模型 - */ - private static boolean put(GenTemplateDetailModel model){ - // 判断 工具类是否初始化完成 - ThrowExceptionUtil.isThrowException(!IS_INIT, - CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - - // 清除缓存 - GenTemplateUtil.del(model); - - return CacheUtil.putHash(CACHE_PREFIX_NAME + model.getParentId(), - model.getId(), model); - } - /** * 删除 字典 * @param model 字典模型 @@ -192,36 +124,10 @@ public class GenTemplateUtil { return true; } - boolean hasNilFlag = CacheUtil.hasNilFlag(CACHE_PREFIX_NAME + - model.getParentId() + ":" + model.getId()); - - GenTemplateDetailModel templateDetailModel = CacheUtil.getHash(GenTemplateDetailModel.class, - CACHE_PREFIX_NAME + model.getParentId(), - model.getId()); - - // 计数器 - int count = 0; - if (hasNilFlag){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delNilFlag(CACHE_PREFIX_NAME + - model.getParentId() + ":" + model.getId()); - if(tmp){ - count--; - } - } - - if (templateDetailModel != null){ - count++; - // 清除空拦截 - boolean tmp = CacheUtil.delHash(CACHE_PREFIX_NAME + - model.getParentId(), model.getId()); - if(tmp){ - count--; - } - } + // 缓存Key + String cacheKey = CacheUtil.formatKey(CACHE_PREFIX_NAME + model.getParentId()); - return count == 0; + return SecurityCache.hDel(redisTemplate, cacheKey, model.getId()); } /** @@ -234,29 +140,18 @@ public class GenTemplateUtil { ThrowExceptionUtil.isThrowException(!IS_INIT, CoreMsg.OTHER_EXCEPTION_UTILS_INIT); - List wrapperList = GenTemplateUtil.getTemplateDetailList(parentId); - if(CollUtil.isEmpty(wrapperList)){ - return true; - } + // 缓存Key + String cacheKey = CacheUtil.formatKey(CACHE_PREFIX_NAME + parentId); - // 计数器 - int count = wrapperList.size(); - for (GenTemplateDetailModel wrapperModel : wrapperList) { - boolean tmp = GenTemplateUtil.del(wrapperModel); - if(tmp){ - count--; - } - } - return count == 0; + return SecurityCache.remove(redisTemplate, cacheKey); } /*** * 处理返回模板明细集合 * @param tempMap Map - * @param id 模板ID * @return List */ - public static List handleDictList(Map tempMap, String id){ + public static List handleDictList(Map tempMap){ List wrapperModels = Lists.newArrayList(); if(CollUtil.isNotEmpty(tempMap)){ for (Map.Entry entry : tempMap.entrySet()) { @@ -278,8 +173,10 @@ public class GenTemplateUtil { * 初始化 */ @Autowired - public void init(IGenTemplateDetailService genTemplateDetailService) { + public void init(IGenTemplateDetailService genTemplateDetailService, + RedisTemplate redisTemplate) { GenTemplateUtil.genTemplateDetailService = genTemplateDetailService; + GenTemplateUtil.redisTemplate = redisTemplate; IS_INIT = true; } diff --git a/opsli-plugins/opsli-plugins-redis/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/opsli-plugins/opsli-plugins-redis/src/main/resources/META-INF/additional-spring-configuration-metadata.json index e02ef412..6e73d4f4 100644 --- a/opsli-plugins/opsli-plugins-redis/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/opsli-plugins/opsli-plugins-redis/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,10 +1,4 @@ { "properties": [ - { - "name": "spring.redis.pushsub.enable", - "type": "java.lang.Boolean", - "defaultValue": false, - "description": "开启消息订阅." - } ] } diff --git a/opsli-starter/src/main/resources/application.yaml b/opsli-starter/src/main/resources/application.yaml index 21990b94..97cfbc9d 100644 --- a/opsli-starter/src/main/resources/application.yaml +++ b/opsli-starter/src/main/resources/application.yaml @@ -54,21 +54,11 @@ spring: # allow-bean-definition-overriding: true # 缓存配置项 - cache-conf: + cache: # 前缀 prefix: opsli - # 一级缓存 ---- EhCache 配置 - cache: - # 是否启用本地缓存 (默认不启用, 如果业务对于缓存依赖较高可启用本地缓存作为一级缓存) - enable: false - # 加载配置文件 - jcache: - config: classpath:config/ehcache-opsli.xml # 二级缓存 ---- Redis 配置 redis: - # 开启消息订阅 - pushsub: - enable: true lettuce: pool: max-active: 8 #最大连接数据库连接数,设 0 为没有限制 diff --git a/opsli-starter/src/main/resources/config/ehcache-opsli.xml b/opsli-starter/src/main/resources/config/ehcache-opsli.xml deleted file mode 100644 index f2888992..00000000 --- a/opsli-starter/src/main/resources/config/ehcache-opsli.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - java.lang.String - java.lang.Object - - 2000 - - - - - - - - - - 21600 - - - - \ No newline at end of file