Redis分布锁锁加入Redisson优化

v1.4.1
Parker 4 years ago
parent ffbacc697e
commit c4bba95fad

@ -54,6 +54,13 @@
<version>${plugins.version}</version>
</dependency>
<!-- 引入软防火墙插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-waf</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- ———————————————————— 集成Shiro鉴权安全认证 - 开始 ———————————————————— -->
<dependency>
<groupId>org.crazycake</groupId>
@ -77,4 +84,4 @@
</dependencies>
</project>
</project>

@ -31,9 +31,6 @@ public class GlobalProperties {
/** 是否开启演示模式 */
private boolean enableDemo;
/** 软防火墙 */
private Waf waf;
/** 认证类 */
private Auth auth;
@ -46,33 +43,6 @@ public class GlobalProperties {
// ============== 内部类 =============
/**
*
*/
@Data
@EqualsAndHashCode(callSuper = false)
public static class Waf {
/** 是否生效 */
private boolean enable;
/** xss 过滤 */
private boolean xssFilter;
/** sql 过滤 */
private boolean sqlFilter;
/** 过滤器需要过滤的路径 */
private Set<String> urlPatterns;
/** 过滤器需要排除过滤的路径 */
private Set<String> urlExclusion;
/** 过滤器的优先级,值越小优先级越高 */
private int order;
}
/**
* Web
*/

@ -120,7 +120,7 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// 如果开启缓存 先从缓存读
if(hotDataFlag){
model = WrapperUtil.transformInstance(
CacheUtil.getTimed(entityClazz, CacheConstants.HOT_DATA_PREFIX +":"+ id)
CacheUtil.getTimed(entityClazz, CacheConstants.HOT_DATA_PREFIX +"::"+ id)
, modelClazz);
if(model != null){
return model;
@ -130,12 +130,12 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
boolean hasNilFlag = false;
// 如果开启缓存 防止缓存穿透判断
if(hotDataFlag){
hasNilFlag = CacheUtil.hasNilFlag("get:" + id);
hasNilFlag = CacheUtil.hasNilFlag("get::" + id);
}
if(!hasNilFlag){
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName("getLock:"+id)
redisLock.setLockName("getLock::"+id)
.setAcquireTimeOut(3000L)
.setLockTimeOut(10000L);
// 这里增加分布式锁 防止缓存击穿
@ -149,7 +149,7 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
model = WrapperUtil.transformInstance(
CacheUtil.getTimed(entityClazz, CacheConstants.HOT_DATA_PREFIX +":"+ id)
CacheUtil.getTimed(entityClazz, CacheConstants.HOT_DATA_PREFIX +"::"+ id)
, modelClazz);
if(model != null){
return model;
@ -178,7 +178,7 @@ public abstract class BaseRestController <T extends BaseEntity, E extends ApiWra
}
}else {
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag("get:" + id);
CacheUtil.putNilFlag("get::" + id);
}
}
}

@ -299,7 +299,7 @@ public class CacheUtil {
if(isSaveLocal){
// 获得缓存Json
cacheJson = ehCachePlugin.get(CacheConstants.EHCACHE_SPACE,
cacheKey +":"+ field, JSONObject.class);
cacheKey +"::"+ field, JSONObject.class);
if(cacheJson != null){
return cacheJson.get(JSON_KEY);
}
@ -312,7 +312,7 @@ public class CacheUtil {
if(isSaveLocal){
//存入EhCache
ehCachePlugin.put(CacheConstants.EHCACHE_SPACE,
cacheKey + ":" + field, cacheJson);
cacheKey + "::" + field, cacheJson);
}
}
@ -474,7 +474,7 @@ public class CacheUtil {
String cacheKey = CacheUtil.handleKey(CacheType.EDEN_HASH, key);
// 删除 EhCache
boolean ehcacheRet = ehCachePlugin.delete(CacheConstants.EHCACHE_SPACE,cacheKey +":"+ field);
boolean ehcacheRet = ehCachePlugin.delete(CacheConstants.EHCACHE_SPACE,cacheKey +"::"+ field);
if(ehcacheRet){
count--;
}
@ -504,7 +504,7 @@ public class CacheUtil {
public static boolean putNilFlag(String key) {
try {
// 处理缓存 key
String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + ":" + key);
String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + "::" + key);
// 存入Redis
return redisPlugin.put(cacheKey, 1, TTL_NIL_DATA_TIME);
}catch (Exception e){
@ -523,7 +523,7 @@ public class CacheUtil {
public static boolean delNilFlag(String key) {
try {
// 处理缓存 key
String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + ":" + key);
String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + "::" + key);
// 删除Redis
return redisPlugin.del(cacheKey);
}catch (Exception e){
@ -543,7 +543,7 @@ public class CacheUtil {
public static boolean hasNilFlag(String key) {
try {
// 处理缓存 key
String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + ":" + key);
String cacheKey = CacheUtil.handleKey(NIL_FLAG_PREFIX + "::" + key);
// 判断Redis 是否 包含当前Nil值
return redisPlugin.get(cacheKey) != null;
}catch (Exception e){
@ -571,7 +571,7 @@ public class CacheUtil {
* @return String
*/
public static String handleKey(CacheType cacheType, String key){
return PREFIX_NAME + cacheType.getName() + ":" +
return PREFIX_NAME + cacheType.getName() + "::" +
key;
}

@ -85,9 +85,9 @@ public class DictHandler implements RedisPushSubHandler{
// 解析 key
String ehKeyByName = CacheUtil.handleKey(CacheType.EDEN_HASH, DictConstants.CACHE_PREFIX_NAME +
dictWrapperModel.getTypeCode() + ":" + dictWrapperModel.getDictName());
dictWrapperModel.getTypeCode() + "::" + dictWrapperModel.getDictName());
String ehKeyByValue = CacheUtil.handleKey(CacheType.EDEN_HASH, DictConstants.CACHE_PREFIX_VALUE +
dictWrapperModel.getTypeCode() + ":" + dictWrapperModel.getDictValue());
dictWrapperModel.getTypeCode() + "::" + dictWrapperModel.getDictValue());
// 缓存更新
if(CacheHandleType.UPDATE == type){

@ -55,7 +55,7 @@ public class HotDataHandler implements RedisPushSubHandler{
}
// 拼装缓存key
String cacheName = CacheUtil.handleKey(CacheConstants.HOT_DATA_PREFIX +":"+ key);
String cacheName = CacheUtil.handleKey(CacheConstants.HOT_DATA_PREFIX +"::"+ key);
if(CacheHandleType.UPDATE == type){
ehCachePlugin.put(CacheConstants.EHCACHE_SPACE, cacheName, value);

@ -93,7 +93,7 @@ public class CacheDataAop {
for (CacheDataEntity cacheDataEntity : cacheDataEntityList) {
// 更新缓存数据
// 热点数据
boolean putRet = CacheUtil.put(CacheConstants.HOT_DATA_PREFIX +":"+ cacheDataEntity.getKey(),
boolean putRet = CacheUtil.put(CacheConstants.HOT_DATA_PREFIX +"::"+ cacheDataEntity.getKey(),
returnValue);
if(putRet){
// 广播缓存数据 - 通知其他服务器同步数据
@ -143,7 +143,7 @@ public class CacheDataAop {
for (CacheDataEntity cacheDataEntity : cacheDataEntityList) {
// 更新缓存数据 - 删除缓存
boolean delRet = CacheUtil.del(CacheConstants.HOT_DATA_PREFIX +":"+ cacheDataEntity.getKey());
boolean delRet = CacheUtil.del(CacheConstants.HOT_DATA_PREFIX +"::"+ cacheDataEntity.getKey());
if(delRet){
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(

@ -59,12 +59,6 @@ public enum CoreMsg implements BaseMsg {
CACHE_DEL_EXCEPTION(10406, "无法清除缓存,请稍后再试"),
/**
*
*/
WAF_EXCEPTION_XSS(10500, "包含非法字符!"),
WAF_EXCEPTION_SQL(10501, "包含非法字符!"),
/** 演示模式 */
EXCEPTION_ENABLE_DEMO(10600,"演示模式不允许操作"),

@ -45,7 +45,7 @@ public class RedisCacheManager implements CacheManager {
Cache cache = caches.get(name);
if (cache == null) {
cache = new RedisCache<K, V>(redisManager,keyPrefix + name + ":", expire, principalIdFieldName);
cache = new RedisCache<K, V>(redisManager,keyPrefix + name + "::", expire, principalIdFieldName);
caches.put(name, cache);
}
return cache;
@ -82,4 +82,4 @@ public class RedisCacheManager implements CacheManager {
public void setPrincipalIdFieldName(String principalIdFieldName) {
this.principalIdFieldName = principalIdFieldName;
}
}
}

@ -25,10 +25,10 @@ package org.opsli.core.security.shiro.utils;
public class RedisKeys {
public static String getSysConfigKey(String key){
return "system:config:" + key;
return "system::config::" + key;
}
public static String getShiroSessionKey(String key){
return "sessionid:" + key;
return "sessionid::" + key;
}
}

@ -17,6 +17,7 @@ package org.opsli.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
@ -28,9 +29,8 @@ import org.opsli.api.wrapper.system.dict.DictWrapper;
import org.opsli.common.constants.DictConstants;
import org.opsli.common.enums.CacheType;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.core.msg.CoreMsg;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
@ -38,7 +38,6 @@ import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
@ -58,9 +57,6 @@ public class DictUtil {
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins;
/** 字典Service */
private static DictDetailApi dictDetailApi;
@ -70,51 +66,46 @@ public class DictUtil {
* @param typeCode Code
* @param dictValue
* @param defaultVal
* @return
* @return String
*/
public static String getDictNameByValue(String typeCode, String dictValue, String defaultVal){
// 缓存Key
String cacheKey = DictConstants.CACHE_PREFIX_VALUE + typeCode;
// 缓存Key + VALUE
String cacheKeyVal = cacheKey + "::" + dictValue;
// 字典名称
String dictName = null;
String dictName = "";
DictDetailModel cacheModel = CacheUtil.getHash(DictDetailModel.class, DictConstants.CACHE_PREFIX_VALUE + typeCode,
DictDetailModel cacheModel = CacheUtil.getHash(DictDetailModel.class, cacheKey,
dictValue);
if (cacheModel != null){
dictName = cacheModel.getDictName();
// 如果缓存有值 直接返回
if (cacheModel != null &&
StringUtils.isNotEmpty(cacheModel.getDictName())){
return cacheModel.getDictName();
}
if (StringUtils.isNotEmpty(dictName)){
return dictName;
}
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(DictConstants.CACHE_PREFIX_VALUE + typeCode + ":" + dictValue);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKeyVal);
if(hasNilFlag){
return defaultVal;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(DictConstants.CACHE_PREFIX_VALUE + typeCode + ":" + dictValue)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
return defaultVal;
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKeyVal)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
cacheModel = CacheUtil.getHash(DictDetailModel.class, DictConstants.CACHE_PREFIX_VALUE + typeCode,
cacheModel = CacheUtil.getHash(DictDetailModel.class, cacheKey,
dictValue);
if (cacheModel != null){
dictName = cacheModel.getDictName();
}
if (StringUtils.isNotEmpty(dictName)){
return dictName;
// 如果缓存有值 直接返回
if (cacheModel != null &&
StringUtils.isNotEmpty(cacheModel.getDictName())){
return cacheModel.getDictName();
}
// 查询数据库 并保存到缓存内
@ -123,15 +114,10 @@ public class DictUtil {
List<DictDetailModel> dictDetailModels = resultVo.getData();
for (DictDetailModel model : dictDetailModels) {
if(model.getDictValue().equals(dictValue)){
// 名称
dictName = model.getDictName();
DictWrapper dictWrapperModel = new DictWrapper();
dictWrapperModel.setTypeCode(model.getTypeCode());
dictWrapperModel.setDictName(model.getDictName());
dictWrapperModel.setDictValue(model.getDictValue());
dictWrapperModel.setModel(model);
// 保存至缓存
DictUtil.put(dictWrapperModel);
DictWrapper dictWrapper = DictUtil.putByModel(model);
// 缓存名
dictName = dictWrapper.getDictName();
break;
}
}
@ -141,15 +127,15 @@ public class DictUtil {
log.error(e.getMessage(),e);
return defaultVal;
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 释放锁
DistributedLockUtil.unlock(cacheKeyVal);
}
// 如果名称还是 为空 则赋默认值
if(StringUtils.isEmpty(dictName)){
// 加入缓存防穿透
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(DictConstants.CACHE_PREFIX_VALUE + typeCode + ":" + dictValue);
CacheUtil.putNilFlag(cacheKeyVal);
dictName = defaultVal;
}
return dictName;
@ -160,48 +146,45 @@ public class DictUtil {
* @param typeCode Code
* @param dictName
* @param defaultVal
* @return
* @return String
*/
public static String getDictValueByName(String typeCode, String dictName, String defaultVal){
// 缓存Key
String cacheKey = DictConstants.CACHE_PREFIX_NAME + typeCode;
// 缓存Key + VALUE
String cacheKeyVal = cacheKey + "::" + dictName;
// 字典值
String dictValue = null;
String dictValue = "";
DictDetailModel cacheModel = CacheUtil.getHash(DictDetailModel.class, DictConstants.CACHE_PREFIX_NAME + typeCode,
DictDetailModel cacheModel = CacheUtil.getHash(DictDetailModel.class, cacheKey,
dictName);
if (cacheModel != null){
dictValue = cacheModel.getDictValue();
}
if (StringUtils.isNotEmpty(dictValue)){
return dictValue;
// 如果缓存有值 直接返回
if (cacheModel != null &&
StringUtils.isNotEmpty(cacheModel.getDictValue())){
return cacheModel.getDictValue();
}
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(DictConstants.CACHE_PREFIX_NAME + typeCode + ":" + dictName);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKeyVal);
if(hasNilFlag){
return defaultVal;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(DictConstants.CACHE_PREFIX_NAME + typeCode + ":" + dictName)
.setAcquireTimeOut(3000L)
.setLockTimeOut(10000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
return defaultVal;
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKeyVal)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
cacheModel = CacheUtil.getHash(DictDetailModel.class, DictConstants.CACHE_PREFIX_NAME + typeCode,
cacheModel = CacheUtil.getHash(DictDetailModel.class, cacheKey,
dictName);
if (cacheModel != null){
dictValue = cacheModel.getDictValue();
}
if (StringUtils.isNotEmpty(dictValue)){
return dictValue;
// 如果缓存有值 直接返回
if (cacheModel != null &&
StringUtils.isNotEmpty(cacheModel.getDictValue())){
return cacheModel.getDictValue();
}
// 查询数据库 并保存到缓存内
@ -210,15 +193,10 @@ public class DictUtil {
List<DictDetailModel> dictDetailModels = resultVo.getData();
for (DictDetailModel model : dictDetailModels) {
if(model.getDictName().equals(dictName)){
// 值
dictValue = model.getDictValue();
DictWrapper dictWrapperModel = new DictWrapper();
dictWrapperModel.setTypeCode(model.getTypeCode());
dictWrapperModel.setDictName(model.getDictName());
dictWrapperModel.setDictValue(model.getDictValue());
dictWrapperModel.setModel(model);
// 保存至缓存
DictUtil.put(dictWrapperModel);
DictWrapper dictWrapper = DictUtil.putByModel(model);
// 值
dictValue = dictWrapper.getDictValue();
break;
}
}
@ -228,16 +206,15 @@ public class DictUtil {
log.error(e.getMessage(),e);
return defaultVal;
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 释放锁
DistributedLockUtil.unlock(cacheKeyVal);
}
// 如果值还是 为空 则赋默认值
if(StringUtils.isEmpty(dictValue)){
// 加入缓存防穿透
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(DictConstants.CACHE_PREFIX_NAME + typeCode + ":" + dictName);
CacheUtil.putNilFlag(cacheKeyVal);
dictValue = defaultVal;
}
return dictValue;
@ -245,82 +222,42 @@ public class DictUtil {
/**
* code
* @param typeCode
* @return
* @param typeCode
* @return List
*/
public static List<DictWrapper> getDictList(String typeCode){
List<DictWrapper> dictWrapperModels = Lists.newArrayList();
// 缓存Key
String cacheKey = DictConstants.CACHE_PREFIX_NAME + typeCode;
List<DictWrapper> dictWrapperModels;
try {
String key = CacheUtil.handleKey(CacheType.EDEN_HASH, DictConstants.CACHE_PREFIX_VALUE + typeCode);
Map<Object, Object> dictMap = redisPlugin.hGetAll(key);
Set<Map.Entry<Object, Object>> entries = dictMap.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
// 赋值
JSONObject jsonObject = (JSONObject) entry.getValue();
if(jsonObject == null){
continue;
}
JSONObject dataJson = jsonObject.getJSONObject(CacheUtil.JSON_KEY);
if(dataJson == null){
continue;
}
DictDetailModel model = dataJson.toJavaObject(DictDetailModel.class);
DictWrapper dictWrapperModel = new DictWrapper();
dictWrapperModel.setTypeCode(typeCode);
dictWrapperModel.setDictName(model.getDictName());
dictWrapperModel.setDictValue(model.getDictValue());
dictWrapperModels.add(dictWrapperModel);
}
if(!dictWrapperModels.isEmpty()){
// 排序
return sortDictWrappers(dictWrapperModels);
String key = CacheUtil.handleKey(CacheType.EDEN_HASH, cacheKey);
// 处理集合数据
dictWrapperModels = handleDictList(redisPlugin.hGetAll(key), typeCode);
if(CollUtil.isNotEmpty(dictWrapperModels)){
return dictWrapperModels;
}
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(DictConstants.CACHE_PREFIX_LIST + typeCode);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return dictWrapperModels;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(DictConstants.CACHE_PREFIX_LIST + typeCode)
.setAcquireTimeOut(3000L)
.setLockTimeOut(10000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return dictWrapperModels;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
key = CacheUtil.handleKey(CacheType.EDEN_HASH, DictConstants.CACHE_PREFIX_VALUE + typeCode);
dictMap = redisPlugin.hGetAll(key);
entries = dictMap.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
// 赋值
JSONObject jsonObject = (JSONObject) entry.getValue();
if(jsonObject == null){
continue;
}
JSONObject dataJson = jsonObject.getJSONObject(CacheUtil.JSON_KEY);
if(dataJson == null){
continue;
}
DictDetailModel model = dataJson.toJavaObject(DictDetailModel.class);
DictWrapper dictWrapperModel = new DictWrapper();
dictWrapperModel.setTypeCode(typeCode);
dictWrapperModel.setDictName(model.getDictName());
dictWrapperModel.setDictValue(model.getDictValue());
dictWrapperModel.setModel(model);
dictWrapperModels.add(dictWrapperModel);
}
if(!dictWrapperModels.isEmpty()){
// 排序
return sortDictWrappers(dictWrapperModels);
key = CacheUtil.handleKey(CacheType.EDEN_HASH, cacheKey);
// 处理集合数据
dictWrapperModels = handleDictList(redisPlugin.hGetAll(key), typeCode);
if(CollUtil.isNotEmpty(dictWrapperModels)){
return dictWrapperModels;
}
@ -328,15 +265,14 @@ public class DictUtil {
ResultVo<List<DictDetailModel>> resultVo = dictDetailApi.findListByTypeCode(typeCode);
if(resultVo.isSuccess()){
List<DictDetailModel> dictDetailModels = resultVo.getData();
for (DictDetailModel model : dictDetailModels) {
DictWrapper dictWrapperModel = new DictWrapper();
dictWrapperModel.setTypeCode(model.getTypeCode());
dictWrapperModel.setDictName(model.getDictName());
dictWrapperModel.setDictValue(model.getDictValue());
dictWrapperModel.setModel(model);
dictWrapperModels.add(dictWrapperModel);
// 保存至缓存
DictUtil.put(dictWrapperModel);
// 处理数据库查询数据
if(CollUtil.isNotEmpty(dictDetailModels)){
dictWrapperModels = Lists.newArrayListWithCapacity(dictDetailModels.size());
for (DictDetailModel model : dictDetailModels) {
// 保存至缓存
DictWrapper dictWrapper = DictUtil.putByModel(model);
dictWrapperModels.add(dictWrapper);
}
}
}
@ -344,16 +280,16 @@ public class DictUtil {
log.error(e.getMessage(),e);
return dictWrapperModels;
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
// 如果值还是 为空 则赋默认值
if(dictWrapperModels.isEmpty()){
if(CollUtil.isEmpty(dictWrapperModels)){
// 加入缓存防穿透
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(DictConstants.CACHE_PREFIX_LIST + typeCode );
CacheUtil.putNilFlag(cacheKey);
}
}catch (Exception e){
@ -367,10 +303,14 @@ public class DictUtil {
/**
*
* @param dictWrapperModels
* @return
* @param dictWrapperModels Model
* @return List
*/
private static List<DictWrapper> sortDictWrappers(List<DictWrapper> dictWrapperModels) {
// 非法判读
if(dictWrapperModels == null){
return null;
}
ListUtil.sort(dictWrapperModels, (o1, o2) -> {
int oInt1 = Integer.MAX_VALUE;
int oInt2 = Integer.MAX_VALUE;
@ -392,7 +332,21 @@ public class DictUtil {
/**
*
* @param model
* @return
*/
private static DictWrapper putByModel(DictDetailModel model){
DictWrapper dictWrapperModel = new DictWrapper();
dictWrapperModel.setTypeCode(model.getTypeCode());
dictWrapperModel.setDictName(model.getDictName());
dictWrapperModel.setDictValue(model.getDictValue());
dictWrapperModel.setModel(model);
// 保存至缓存
DictUtil.put(dictWrapperModel);
return dictWrapperModel;
}
/**
*
* @param model
*/
public static void put(DictWrapper model){
// 清除缓存
@ -407,7 +361,7 @@ public class DictUtil {
/**
*
* @param model
* @return
* @return boolean
*/
public static boolean del(DictWrapper model){
if(model == null){
@ -415,9 +369,9 @@ public class DictUtil {
}
boolean hasNilFlagByName = CacheUtil.hasNilFlag(DictConstants.CACHE_PREFIX_NAME +
model.getTypeCode() + ":" + model.getDictName());
model.getTypeCode() + "::" + model.getDictName());
boolean hasNilFlagByValue = CacheUtil.hasNilFlag(DictConstants.CACHE_PREFIX_VALUE +
model.getTypeCode() + ":" + model.getDictValue());
model.getTypeCode() + "::" + model.getDictValue());
DictWrapper dictByName = CacheUtil.getHash(DictWrapper.class,
DictConstants.CACHE_PREFIX_NAME + model.getTypeCode(),
@ -432,7 +386,7 @@ public class DictUtil {
count++;
// 清除空拦截
boolean tmp = CacheUtil.delNilFlag(DictConstants.CACHE_PREFIX_NAME +
model.getTypeCode() + ":" + model.getDictName());
model.getTypeCode() + "::" + model.getDictName());
if(tmp){
count--;
}
@ -442,7 +396,7 @@ public class DictUtil {
count++;
// 清除空拦截
boolean tmp = CacheUtil.delNilFlag(DictConstants.CACHE_PREFIX_VALUE +
model.getTypeCode() + ":" + model.getDictValue());
model.getTypeCode() + "::" + model.getDictValue());
if(tmp){
count--;
}
@ -474,7 +428,7 @@ public class DictUtil {
/**
* typeCode
* @param typeCode
* @return
* @return boolean
*/
public static boolean delAll(String typeCode){
List<DictWrapper> dictWrapperList = DictUtil.getDictList(typeCode);
@ -493,6 +447,41 @@ public class DictUtil {
return count == 0;
}
/***
*
* @param dictMap Map
* @param typeCode
* @return List
*/
public static List<DictWrapper> handleDictList(Map<Object, Object> dictMap, String typeCode){
if(CollUtil.isEmpty(dictMap)){
return null;
}
List<DictWrapper> dictWrapperModels = Lists.newArrayList();
for (Map.Entry<Object, Object> entry : dictMap.entrySet()) {
// 赋值
JSONObject jsonObject = (JSONObject) entry.getValue();
if(jsonObject == null){
continue;
}
Object data = jsonObject.get(CacheUtil.JSON_KEY);
if(data == null){
continue;
}
DictDetailModel model = Convert.convert(DictDetailModel.class, data);
DictWrapper dictWrapperModel = new DictWrapper();
dictWrapperModel.setTypeCode(typeCode);
dictWrapperModel.setDictName(model.getDictName());
dictWrapperModel.setDictValue(model.getDictValue());
dictWrapperModels.add(dictWrapperModel);
}
// 返回排序后 list
return CollUtil.isNotEmpty(dictWrapperModels)?sortDictWrappers(dictWrapperModels):null;
}
// ===================================
@ -501,13 +490,9 @@ public class DictUtil {
DictUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) {
DictUtil.redisLockPlugins = redisLockPlugins;
}
@Autowired
public void setDictDetailApi(DictDetailApi dictDetailApi) {
DictUtil.dictDetailApi = dictDetailApi;
}
}

@ -0,0 +1,91 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.user.UserApi;
import org.opsli.api.wrapper.system.user.UserOrgRefModel;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.OrgMsgFactory;
import org.opsli.core.msg.CoreMsg;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redisson.RedissonLock;
import org.springframework.beans.factory.annotation.Autowired;
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
@Lazy(false)
public class DistributedLockUtil {
/** 锁有效时长为 默认10秒 */
private static final int LEASE_TIME = 10;
/** Redisson 分布式锁 */
private static RedissonLock REDISSON_LOCK;
/**
*
* @param lockName
* @return boolean
*/
public static boolean lock(String lockName){
boolean isLock = true;
// 分布式上锁
if(REDISSON_LOCK != null){
isLock = REDISSON_LOCK.tryLock(CacheUtil.getPrefixName() + lockName, LEASE_TIME);
}
return isLock;
}
/**
*
* @param lockName
*/
public static void unlock(String lockName){
// 释放锁
if(REDISSON_LOCK != null){
REDISSON_LOCK.unlockByThread(CacheUtil.getPrefixName() + lockName);
}
}
// =============
/**
*
* @param redissonLock
*/
@Autowired
public void init(RedissonLock redissonLock){
DistributedLockUtil.REDISSON_LOCK = redissonLock;
}
}

@ -22,9 +22,8 @@ import org.opsli.api.web.system.menu.MenuApi;
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.plugins.redis.RedisLockPlugins;
import org.opsli.core.msg.CoreMsg;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
@ -52,9 +51,6 @@ public class MenuUtil {
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins;
/** 菜单 Api */
private static MenuApi menuApi;
@ -65,35 +61,32 @@ public class MenuUtil {
* @return
*/
public static MenuModel getMenuByCode(String menuCode){
// 缓存Key
String cacheKey = PREFIX_CODE + menuCode;
// 先从缓存里拿
MenuModel menuModel = CacheUtil.getTimed(MenuModel.class, PREFIX_CODE + menuCode);
MenuModel menuModel = CacheUtil.getTimed(MenuModel.class, cacheKey);
if (menuModel != null){
return menuModel;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + menuCode);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_CODE + menuCode)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
menuModel = CacheUtil.getTimed(MenuModel.class, PREFIX_CODE + menuCode);
menuModel = CacheUtil.getTimed(MenuModel.class, cacheKey);
if (menuModel != null){
return menuModel;
}
@ -103,18 +96,18 @@ public class MenuUtil {
if(resultVo.isSuccess()){
menuModel = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_CODE + menuCode, menuModel);
CacheUtil.put(cacheKey, menuModel);
}
}catch (Exception e){
log.error(e.getMessage(),e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(menuModel == null){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_CODE + menuCode);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -177,13 +170,9 @@ public class MenuUtil {
MenuUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) {
MenuUtil.redisLockPlugins = redisLockPlugins;
}
@Autowired
public void setMenuApi(MenuApi menuApi) {
MenuUtil.menuApi = menuApi;
}
}

@ -22,9 +22,8 @@ import org.opsli.api.web.system.user.UserApi;
import org.opsli.api.wrapper.system.user.UserOrgRefModel;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.OrgMsgFactory;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.core.msg.CoreMsg;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
@ -52,9 +51,6 @@ public class OrgUtil {
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins;
/** 用户 Api */
private static UserApi userApi;
@ -65,35 +61,32 @@ public class OrgUtil {
* @return
*/
public static UserOrgRefModel getOrgByUserId(String userId){
// 缓存Key
String cacheKey = PREFIX_CODE + userId;
// 先从缓存里拿
UserOrgRefModel orgRefModel = CacheUtil.getTimed(UserOrgRefModel.class, PREFIX_CODE + userId);
UserOrgRefModel orgRefModel = CacheUtil.getTimed(UserOrgRefModel.class, cacheKey);
if (orgRefModel != null){
return orgRefModel;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
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){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
orgRefModel = CacheUtil.getTimed(UserOrgRefModel.class, PREFIX_CODE + userId);
orgRefModel = CacheUtil.getTimed(UserOrgRefModel.class, cacheKey);
if (orgRefModel != null){
return orgRefModel;
}
@ -103,18 +96,18 @@ public class OrgUtil {
if(resultVo.isSuccess()){
orgRefModel = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_CODE + userId, orgRefModel);
CacheUtil.put(cacheKey, orgRefModel);
}
}catch (Exception e){
log.error(e.getMessage(),e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(orgRefModel == null){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_CODE + userId);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -176,11 +169,6 @@ public class OrgUtil {
OrgUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) {
OrgUtil.redisLockPlugins = redisLockPlugins;
}
@Autowired
public void setUserApi(UserApi userApi) {
OrgUtil.userApi = userApi;

@ -71,7 +71,7 @@ public class SearchHisUtil {
// 获得当前用户
UserModel user = UserUtil.getUser();
String cacheKey = CacheUtil.getPrefixName() + CACHE_PREFIX + user.getUsername() + ":" + key;
String cacheKey = CacheUtil.getPrefixName() + CACHE_PREFIX + user.getUsername() + "::" + key;
return redisPlugin.zReverseRange(cacheKey, 0, count - 1);
}
@ -97,7 +97,7 @@ public class SearchHisUtil {
}
String cacheKey = CacheUtil.getPrefixName() + CACHE_PREFIX + user.getUsername() + ":" + key;
String cacheKey = CacheUtil.getPrefixName() + CACHE_PREFIX + user.getUsername() + "::" + key;
String val = values[0];
// 记录

@ -22,9 +22,8 @@ import org.opsli.api.web.system.tenant.TenantApi;
import org.opsli.api.wrapper.system.tenant.TenantModel;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.TenantMsgFactory;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.core.msg.CoreMsg;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
@ -52,9 +51,6 @@ public class TenantUtil {
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins;
/** 租户 Api */
private static TenantApi tenantApi;
@ -65,35 +61,32 @@ public class TenantUtil {
* @return
*/
public static TenantModel getTenant(String tenantId){
// 缓存Key
String cacheKey = PREFIX_CODE + tenantId;
// 先从缓存里拿
TenantModel tenantModel = CacheUtil.getTimed(TenantModel.class, PREFIX_CODE + tenantId);
TenantModel tenantModel = CacheUtil.getTimed(TenantModel.class, cacheKey);
if (tenantModel != null){
return tenantModel;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + tenantId);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_CODE + tenantId)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
tenantModel = CacheUtil.getTimed(TenantModel.class, PREFIX_CODE + tenantId);
tenantModel = CacheUtil.getTimed(TenantModel.class, cacheKey);
if (tenantModel != null){
return tenantModel;
}
@ -103,18 +96,18 @@ public class TenantUtil {
if(resultVo.isSuccess()){
tenantModel = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_CODE + tenantId, tenantModel);
CacheUtil.put(cacheKey, tenantModel);
}
}catch (Exception e){
log.error(e.getMessage(),e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(tenantModel == null){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_CODE + tenantId);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -177,13 +170,9 @@ public class TenantUtil {
TenantUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) {
TenantUtil.redisLockPlugins = redisLockPlugins;
}
@Autowired
public void setTenantApi(TenantApi tenantApi) {
TenantUtil.tenantApi = tenantApi;
}
}

@ -74,12 +74,10 @@ public class UserTokenUtil {
private static RedisPlugin redisPlugin;
/**
* user Token
* @param user
* @return
* @return UserTokenUtil.TokenRet
*/
public static ResultVo<UserTokenUtil.TokenRet> createToken(UserModel user) {
if (user == null) {
@ -149,7 +147,7 @@ public class UserTokenUtil {
/**
* Token ID
* @param token token
* @return
* @return String
*/
public static String getUserIdByToken(String token) {
if(StringUtils.isEmpty(token)){
@ -165,7 +163,7 @@ public class UserTokenUtil {
/**
* Token username
* @param token token
* @return
* @return String
*/
public static String getUserNameByToken(String token) {
if(StringUtils.isEmpty(token)){

@ -17,10 +17,6 @@ package org.opsli.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
@ -35,17 +31,13 @@ import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.UserMsgFactory;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.opsli.plugins.redisson.RedissonLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
@ -73,9 +65,6 @@ public class UserUtil {
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redisson 分布式锁 */
private static RedissonLock REDISSON_LOCK;
/** 用户Service */
private static UserApi userApi;
@ -127,10 +116,8 @@ public class UserUtil {
}
try {
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
@ -157,11 +144,8 @@ public class UserUtil {
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(userModel == null){
@ -197,10 +181,8 @@ public class UserUtil {
}
try {
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
@ -222,11 +204,8 @@ public class UserUtil {
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(userModel == null){
@ -264,10 +243,8 @@ public class UserUtil {
}
try {
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
@ -290,11 +267,8 @@ public class UserUtil {
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(CollUtil.isEmpty(roles)){
@ -334,10 +308,8 @@ public class UserUtil {
}
try {
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
@ -360,11 +332,8 @@ public class UserUtil {
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(CollUtil.isEmpty(permissions)){
@ -404,10 +373,8 @@ public class UserUtil {
try {
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 分布式加锁
if(!DistributedLockUtil.lock(cacheKey)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
@ -430,11 +397,8 @@ public class UserUtil {
}catch (Exception e){
log.error(e.getMessage(), e);
}finally {
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
// 释放锁
DistributedLockUtil.unlock(cacheKey);
}
if(CollUtil.isEmpty(menus)){
@ -675,14 +639,13 @@ public class UserUtil {
* @param globalProperties
*/
@Autowired
public void init(GlobalProperties globalProperties, RedissonLock redissonLock){
public void init(GlobalProperties globalProperties){
if(globalProperties != null && globalProperties.getAuth() != null
&& globalProperties.getAuth().getToken() != null
){
// 获得 超级管理员
UserUtil.SUPER_ADMIN = globalProperties.getAuth().getSuperAdmin();
}
UserUtil.REDISSON_LOCK = redissonLock;
}
}

@ -18,12 +18,6 @@
"defaultValue": false,
"description": "是否启用本地缓存 (默认不启用, 如果业务对于缓存依赖较高可启用本地缓存作为一级缓存)."
},
{
"name": "spring.redis.pushsub.enable",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "开启消息订阅."
},
{
"name": "knife4j.basic.enable",
"type": "java.lang.Boolean",
@ -81,51 +75,6 @@
{
"name": "opsli.waf.enable",
"sourceType": "org.opsli.core.autoconfigure.properties.GlobalProperties$Waf",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "软防火墙是否开启."
},
{
"name": "opsli.waf.xss-filter",
"sourceType": "org.opsli.core.autoconfigure.properties.GlobalProperties$Waf",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "软防火墙 xss 过滤开启状态."
},
{
"name": "opsli.waf.sql-filter",
"sourceType": "org.opsli.core.autoconfigure.properties.GlobalProperties$Waf",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "软防火墙 sql 过滤开启状态."
},
{
"name": "opsli.waf.url-patterns",
"sourceType": "org.opsli.core.autoconfigure.properties.GlobalProperties$Waf",
"type": "java.util.Set<java.lang.String>",
"defaultValue": [
"/*"
],
"description": "软防火墙 过滤器需要过滤的路径."
},
{
"name": "opsli.waf.url-exclusion",
"sourceType": "org.opsli.core.autoconfigure.properties.GlobalProperties$Waf",
"type": "java.util.Set<java.lang.String>",
"description": "软防火墙 过滤器需要排除过滤的路径."
},
{
"name": "opsli.waf.order",
"sourceType": "org.opsli.core.autoconfigure.properties.GlobalProperties$Waf",
"type": "java.lang.Integer",
"defaultValue": 0,
"description": "软防火墙 过滤器的优先级,值越小优先级越高."
},
{
"name": "opsli.web.upload-path",

@ -23,12 +23,12 @@ import org.opsli.core.creater.exception.CreaterException;
import org.opsli.core.creater.msg.CreaterMsg;
import org.opsli.core.creater.strategy.sync.mysql.entity.FieldTypeAttribute;
import org.opsli.core.creater.strategy.sync.mysql.enums.MySQLSyncColumnType;
import org.opsli.core.waf.util.SQLFilterKit;
import org.opsli.modulars.creater.column.wrapper.CreaterTableColumnModel;
import org.opsli.modulars.creater.general.actuator.SQLActuator;
import org.opsli.modulars.creater.table.service.ITableService;
import org.opsli.modulars.creater.table.wrapper.CreaterTableAndColumnModel;
import org.opsli.modulars.creater.table.wrapper.CreaterTableModel;
import org.opsli.plugins.waf.util.SQLFilterKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@ -80,12 +80,11 @@ public class RedisPluginConfig {
*
*
*
* @return
* @return RedisScriptCache
*/
@Bean
public RedisScriptCache loadScripts() {
RedisScriptCache redisScriptCache = new RedisScriptCache();
RedisScriptsEnum[] scriptEnums = RedisScriptsEnum.values();
for (RedisScriptsEnum scriptEnum : scriptEnums) {
String path = scriptEnum.getPath();
@ -93,47 +92,11 @@ public class RedisPluginConfig {
try {
ClassPathResource resource = new ClassPathResource(path);
InputStream inputStream = resource.getInputStream();
// List<String> readList = Lists.newArrayList();
// IoUtil.readLines(inputStream, StandardCharsets.UTF_8, readList);
// StringBuilder stb = new StringBuilder();
// for (String readLine : readList) {
// stb.append(readLine);
// stb.append("\n");
// }
String read = IoUtil.read(inputStream, StandardCharsets.UTF_8);
// 保存脚本到缓存中
redisScriptCache.putScript(scriptEnum,read);
}catch (Exception ignored){}
}
/**
* Lua Java
* Lua lua IDEALua Lua
*/
// // 拿到state包下 实现了 SystemEventState 接口的,所有子类
// Set<Class<?>> clazzSet = PackageUtil.listSubClazz(RedisPluginScript.class.getPackage().getName(),
// true,
// RedisPluginScript.class
// );
//
// for (Class<?> aClass : clazzSet) {
// // 位运算 去除抽象类
// if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
// continue;
// }
//
// // 通过反射 加载所有的 脚本
// try {
// RedisPluginScript redisPluginScript = (RedisPluginScript) aClass.newInstance();
// redisScriptCache.putScript(redisPluginScript);
// } catch (Exception e) {
// log.error(RedisMsg.EXCEPTION_REFLEX.getMessage());
// }
//
// }
return redisScriptCache;
}

@ -0,0 +1,10 @@
{
"properties": [
{
"name": "spring.redis.pushsub.enable",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "开启消息订阅."
}
]
}

@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.opsli.plugins.redis.conf.RedisPluginConfig

@ -3,12 +3,14 @@ package org.opsli.plugins.redisson;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
/**
* @Description: Redisson
* Redisson
*
* https://github.com/yudiandemingzi/spring-boot-distributed-redisson
* @author xub
* @date 2019/6/19 10:26
*/
@ -17,8 +19,8 @@ public class RedissonLock {
private static final String PREFIX = "lock::";
private RedissonManager redissonManager;
private Redisson redisson;
private RedissonManager redissonManager;
private RedissonClient redisson;
public RedissonLock(RedissonManager redissonManager) {
@ -93,6 +95,18 @@ public class RedissonLock {
redisson.getLock(PREFIX + lockName).unlock();
}
/**
* 线
* @param lockName
*/
public void unlockByThread(String lockName) {
// 是否是当前线程
if(this.isHeldByCurrentThread(lockName)){
// 释放锁
this.unlock(lockName);
}
}
/**
* 线
* @param lockName
@ -112,6 +126,8 @@ public class RedissonLock {
return rLock.isHeldByCurrentThread();
}
// ======================
public RedissonManager getRedissonManager() {
return redissonManager;
}

@ -4,10 +4,11 @@ import cn.hutool.core.util.ClassUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.properties.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import java.lang.reflect.Modifier;
@ -16,21 +17,23 @@ import java.util.Set;
/**
* @Description: Redissonredisson
*
* Redissonredisson
*
* https://github.com/yudiandemingzi/spring-boot-distributed-redisson
* @author xub
* @date 2019/6/19 10:16
*/
@Slf4j
public class RedissonManager {
private final Redisson redisson;
private final RedissonClient redisson;
public RedissonManager(RedissonProperties redissonProperties) {
try {
//通过不同部署方式获得不同config实体
Config config = RedissonConfigFactory.getInstance().createConfig(redissonProperties);
redisson = (Redisson) Redisson.create(config);
redisson = Redisson.create(config);
} catch (Exception e) {
log.error("Redisson 初始化异常", e);
throw new IllegalArgumentException("请输入正确的配置," +
@ -38,7 +41,7 @@ public class RedissonManager {
}
}
public Redisson getRedisson() {
public RedissonClient getRedisson() {
return redisson;
}
@ -97,7 +100,6 @@ public class RedissonManager {
Preconditions.checkNotNull(redissonProperties);
Preconditions.checkNotNull(redissonProperties.getAddress(), "redisson.lock.server.address 不能为空!");
Preconditions.checkNotNull(redissonProperties.getType().getType(), "redisson.lock.server.password 不能为空!");
Preconditions.checkNotNull(redissonProperties.getDatabase(), "redisson.lock.server.database cannot 不能为空");
String connectionType = redissonProperties.getType().getType();
//声明配置上下文
RedissonConfigService redissonConfigService = strategyMap.get(redissonProperties.getType());

@ -3,7 +3,7 @@ package org.opsli.plugins.redisson.annotation;
import java.lang.annotation.*;
/**
* @Description:
*
*
* @author xub
* @date 2019/6/19 9:22
@ -17,7 +17,7 @@ public @interface DistributedLock {
/**
*
*/
String value() default "redisson";
String value() default "opsli::redisson";
/**
*

@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
/**
* @Description: Redisson
* Redisson
*
* @author xub
* @date 2019/6/20 9:34

@ -13,12 +13,12 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
package org.opsli.plugins.redisson.conf;
import lombok.extern.slf4j.Slf4j;
import org.opsli.plugins.redisson.RedissonLock;
import org.opsli.plugins.redisson.RedissonManager;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.properties.RedissonProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@ -34,7 +34,7 @@ import org.springframework.core.annotation.Order;
*/
@Slf4j
@Configuration
@ConditionalOnProperty(name = "redisson.lock.server.enable", havingValue = "true")
@ConditionalOnProperty(prefix = RedissonProperties.PROP_PREFIX, name = "enable", havingValue = "true")
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonConfig {

@ -2,8 +2,9 @@ package org.opsli.plugins.redisson.constant;
/**
* URL
*
* @author xub
* @Description: URL
* @date 2019/6/19 9:09
*/
public enum GlobalConstant {
@ -11,19 +12,19 @@ public enum GlobalConstant {
/** 前缀 */
REDIS_CONNECTION_PREFIX("redis://", "Redis地址配置前缀");
private final String constant_value;
private final String constant_desc;
private final String constantValue;
private final String constantDesc;
GlobalConstant(String constant_value, String constant_desc) {
this.constant_value = constant_value;
this.constant_desc = constant_desc;
GlobalConstant(String constantValue, String constantDesc) {
this.constantValue = constantValue;
this.constantDesc = constantDesc;
}
public String getConstant_value() {
return constant_value;
public String getConstantValue() {
return constantValue;
}
public String getConstant_desc() {
return constant_desc;
public String getConstantDesc() {
return constantDesc;
}
}

@ -17,11 +17,10 @@ package org.opsli.plugins.redisson.enums;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.enums
* @Author: Parker
* @CreateTime: 2020-09-17 23:40
* @Description: Redisson
* Redisson
*
* @author : Parker
* @date 2020-09-17 23:40
*/
public enum RedissonType {
@ -29,7 +28,7 @@ public enum RedissonType {
STANDALONE("standalone", "单节点部署方式"),
SENTINEL("sentinel", "哨兵部署方式"),
CLUSTER("cluster", "集群方式"),
MASTER_SLAVE("master_slave", "主从部署方式");
MASTER_SLAVE("master_slave", "主从部署方式"),
;

@ -1,4 +1,4 @@
package org.opsli.plugins.redisson.entity;
package org.opsli.plugins.redisson.properties;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -7,17 +7,19 @@ import org.opsli.plugins.redisson.enums.RedissonType;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @Description: redis
* redis
*
* @author xub
* @date 2019/6/19 9:35
*/
@ConfigurationProperties(prefix = "redisson.lock.server")
@ConfigurationProperties(prefix = RedissonProperties.PROP_PREFIX)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RedissonProperties {
public static final String PROP_PREFIX = "redisson.lock.server";
/**
*
*/

@ -1,12 +1,12 @@
package org.opsli.plugins.redisson.strategy;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.properties.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.redisson.config.Config;
/**
* @Description: Redisson
* Redisson
*
* @author xub
* @date 2019/6/20 3:35

@ -4,13 +4,13 @@ package org.opsli.plugins.redisson.strategy.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.properties.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
/**
* @Description: Redisson
* Redisson
*
* cluster6(333sharding3)
* : 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384
@ -36,7 +36,7 @@ public class ClusterConfigImpl implements RedissonConfigService {
//设置cluster节点的服务IP和端口
for (String addrToken : addrTokens) {
config.useClusterServers()
.addNodeAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrToken);
.addNodeAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstantValue() + addrToken);
if (StringUtils.isNotBlank(password)) {
config.useClusterServers().setPassword(password);
}

@ -6,16 +6,15 @@ import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.properties.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: Redisson
* Redisson
* : ,,
* : 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381
* @author xub
@ -48,7 +47,7 @@ public class MasterslaveConfigImpl implements RedissonConfigService {
//设置从节点,移除第一个节点,默认第一个为主节点
List<String> slaveList = Lists.newArrayList();
for (String addrToken : addrTokens) {
slaveList.add(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrToken);
slaveList.add(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstantValue() + addrToken);
}
slaveList.remove(0);

@ -4,14 +4,14 @@ package org.opsli.plugins.redisson.strategy.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.properties.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
/**
* @Description: Redis
* Redis
*
* @author xub
* @date 2019/6/19 9:17
@ -41,7 +41,7 @@ public class SentinelConfigImpl implements RedissonConfigService {
}
//设置sentinel节点的服务IP和端口
for (int i = 1; i < addrTokens.length; i++) {
config.useSentinelServers().addSentinelAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrTokens[i]);
config.useSentinelServers().addSentinelAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstantValue() + addrTokens[i]);
}
log.info("初始化[哨兵部署]方式Config,redisAddress:" + address);
} catch (Exception e) {

@ -4,13 +4,13 @@ package org.opsli.plugins.redisson.strategy.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.properties.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
/**
* @Description: Redisson
* Redisson
*
* @author xub
* @date 2019/6/19 10:04
@ -31,7 +31,7 @@ public class StandaloneConfigImpl implements RedissonConfigService {
String address = redissonProperties.getAddress();
String password = redissonProperties.getPassword();
int database = redissonProperties.getDatabase();
String redisAddr = GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + address;
String redisAddr = GlobalConstant.REDIS_CONNECTION_PREFIX.getConstantValue() + address;
config.useSingleServer().setAddress(redisAddr);
config.useSingleServer().setDatabase(database);
//密码可以为空

@ -2,32 +2,32 @@
"properties": [
{
"name": "redisson.lock.server.enable",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"sourceType": "org.opsli.plugins.redisson.properties.RedissonProperties",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "redissonLock 是否启用."
},
{
"name": "redisson.lock.server.address",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"sourceType": "org.opsli.plugins.redisson.properties.RedissonProperties",
"type": "java.lang.String",
"defaultValue": "127.0.0.1:6379",
"description": "redis主机地址ipport有多个用半角逗号分隔."
},
{
"name": "redisson.lock.server.type",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"sourceType": "org.opsli.plugins.redisson.properties.RedissonProperties",
"description": "连接类型支持standalone-单机节点sentinel-哨兵cluster-集群masterslave-主从."
},
{
"name": "redisson.lock.server.password",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"sourceType": "org.opsli.plugins.redisson.properties.RedissonProperties",
"type": "java.lang.String",
"description": "redis 连接密码."
},
{
"name": "redisson.lock.server.database",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"sourceType": "org.opsli.plugins.redisson.properties.RedissonProperties",
"type": "java.lang.Integer",
"defaultValue": 0,
"description": "选取那个数据库 ."

@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.opsli.plugins.redisson.conf.RedissonConfig

@ -21,6 +21,7 @@
<module>opsli-plugins-ehcache</module>
<module>opsli-plugins-excel</module>
<module>opsli-plugins-redisson</module>
<module>opsli-plugins-waf</module>
</modules>
<dependencyManagement>
@ -43,4 +44,4 @@
</dependency>
</dependencies>
</project>
</project>

Loading…
Cancel
Save