优化缓存系统

v1.4.1
Parker 4 years ago
parent e98b06e7fe
commit 60fa1c3bfc

@ -24,6 +24,8 @@ package org.opsli.common.constants;
*/ */
public interface CacheConstants { public interface CacheConstants {
String PREFIX_NAME = "opsli";
/** 热点数据 */ /** 热点数据 */
String HOT_DATA = "hotData"; String HOT_DATA = "hotData";

@ -15,6 +15,7 @@
*/ */
package org.opsli.core.aspect; package org.opsli.core.aspect;
import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
@ -27,6 +28,7 @@ import org.opsli.common.annotation.hotdata.EnableHotData;
import org.opsli.common.annotation.hotdata.HotDataDel; import org.opsli.common.annotation.hotdata.HotDataDel;
import org.opsli.common.annotation.hotdata.HotDataPut; import org.opsli.common.annotation.hotdata.HotDataPut;
import org.opsli.common.constants.CacheConstants; import org.opsli.common.constants.CacheConstants;
import org.opsli.common.utils.Props;
import org.opsli.core.cache.local.CacheUtil; import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.entity.CacheDataEntity; import org.opsli.core.cache.pushsub.entity.CacheDataEntity;
import org.opsli.core.cache.pushsub.enums.CacheType; import org.opsli.core.cache.pushsub.enums.CacheType;
@ -57,7 +59,13 @@ import static org.opsli.common.constants.OrderConstants.HOT_DATA_ORDER;
public class CacheDataAop { public class CacheDataAop {
/** 热点数据前缀 */ /** 热点数据前缀 */
public static final String PREFIX_NAME = "opsli:"; public static final String PREFIX_NAME;
static{
// 缓存前缀
Props props = new Props("application.yaml");
PREFIX_NAME = props.getStr("spring.cache-conf.prefix",CacheConstants.PREFIX_NAME) + ":";
}
@Autowired @Autowired
private RedisPlugin redisPlugin; private RedisPlugin redisPlugin;
@ -80,33 +88,35 @@ public class CacheDataAop {
public Object hotDataPutProcess(ProceedingJoinPoint point) throws Throwable { public Object hotDataPutProcess(ProceedingJoinPoint point) throws Throwable {
Object[] args= point.getArgs(); Object[] args= point.getArgs();
Object returnValue = point.proceed(args); Object returnValue = point.proceed(args);
// 判断 方法上是否使用 HotData注解 如果没有表示开启热数据 则直接跳过 // 判断 方法上是否使用 EnableHotData注解 如果没有表示开启热数据 则直接跳过
Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class); Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class);
if(annotation == null){ if(annotation == null){
return returnValue; return returnValue;
} }
// ====== 如果 使用了 EnableHotData ,表示开启热数据加载 则执行下段代码 List<CacheDataEntity> cacheDataEntityList = this.putHandlerData(point, returnValue);
CacheDataEntity cacheDataEntity = this.putHandlerData(point, returnValue); // 非法判断
if(cacheDataEntity == null){ if(CollUtil.isEmpty(cacheDataEntityList)){
return returnValue; return returnValue;
} }
// 更新缓存数据 for (CacheDataEntity cacheDataEntity : cacheDataEntityList) {
// 热点数据 // 更新缓存数据
if(CacheConstants.HOT_DATA.equals(cacheDataEntity.getCacheName())){ // 热点数据
CacheUtil.putByKeyOriginal(cacheDataEntity.getKey(), returnValue); if(CacheConstants.HOT_DATA.equals(cacheDataEntity.getCacheName())){
} CacheUtil.putByKeyOriginal(cacheDataEntity.getKey(), returnValue);
// 永久数据 }
else if(CacheConstants.EDEN_DATA.equals(cacheDataEntity.getCacheName())) { // 永久数据
CacheUtil.putEdenByKeyOriginal(cacheDataEntity.getKey(), returnValue); else if(CacheConstants.EDEN_DATA.equals(cacheDataEntity.getCacheName())) {
} CacheUtil.putEdenByKeyOriginal(cacheDataEntity.getKey(), returnValue);
}
// 广播缓存数据 - 通知其他服务器同步数据 // 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage( redisPlugin.sendMessage(
CacheDataMsgFactory.createMsg(cacheDataEntity.getType(), CacheDataMsgFactory.createMsg(cacheDataEntity.getType(),
cacheDataEntity.getKey(), returnValue, CacheType.UPDATE) cacheDataEntity.getKey(), returnValue, CacheType.UPDATE)
); );
}
return returnValue; return returnValue;
} }
@ -122,7 +132,7 @@ public class CacheDataAop {
public Object hotDataDelProcess(ProceedingJoinPoint point) throws Throwable { public Object hotDataDelProcess(ProceedingJoinPoint point) throws Throwable {
Object[] args= point.getArgs(); Object[] args= point.getArgs();
Object returnValue = point.proceed(args); Object returnValue = point.proceed(args);
// 判断 方法上是否使用 HotData注解 如果没有表示开启热数据 则直接跳过 // 判断 方法上是否使用 EnableHotData注解 如果没有表示开启热数据 则直接跳过
Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class); Annotation annotation = point.getTarget().getClass().getAnnotation(EnableHotData.class);
if(annotation == null){ if(annotation == null){
return returnValue; return returnValue;
@ -139,9 +149,9 @@ public class CacheDataAop {
return returnValue; return returnValue;
} }
// ====== 如果 使用了 EnableHotData ,表示开启热数据加载 则执行下段代码
List<CacheDataEntity> cacheDataEntityList = this.delHandlerData(point, args); List<CacheDataEntity> cacheDataEntityList = this.delHandlerData(point, args);
if(cacheDataEntityList == null || cacheDataEntityList.size() == 0){ // 非法判断
if(CollUtil.isEmpty(cacheDataEntityList)){
return returnValue; return returnValue;
} }
@ -167,59 +177,44 @@ public class CacheDataAop {
* PUT * PUT
* @param point * @param point
*/ */
private CacheDataEntity putHandlerData(ProceedingJoinPoint point, Object returnValue){ private List<CacheDataEntity> putHandlerData(ProceedingJoinPoint point, Object returnValue){
CacheDataEntity ret;
// 返回值为空直接
if(returnValue == null){
return null;
}
// 这里 只对 继承了 ApiWrapper 的类做处理 // 这里 只对 继承了 ApiWrapper 的类做处理
if(!(returnValue instanceof ApiWrapper)){ if(!(returnValue instanceof ApiWrapper)){
return null; return null;
} }
// 消息集合 后续可能会考虑 多消息存储
List<CacheDataEntity> cacheDataEntities = Lists.newArrayListWithCapacity(1);
// 报错不处理 // 报错不处理
try { try {
String methodName= point.getSignature().getName(); // 获得方法
Class<?> classTarget= point.getTarget().getClass(); Method objMethod = this.getMethod(point);
Class<?>[] par=((MethodSignature) point.getSignature()).getParameterTypes(); if(objMethod == null) return null;
Method objMethod = classTarget.getMethod(methodName, par);
// 获取注解参数 // 获取注解参数
HotDataPut aCache= objMethod.getAnnotation(HotDataPut.class); HotDataPut aCache= objMethod.getAnnotation(HotDataPut.class);
if(aCache != null){ if(aCache != null){
// 类型 // 获得缓存类型
PushSubType type; PushSubType type = this.judgeCacheType(aCache.name());
// key 前缀 if(type == null) {
StringBuilder keyBuf = new StringBuilder(PREFIX_NAME);
// 热点数据
if(CacheConstants.HOT_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.HOT_DATA).append(":");
type = PushSubType.HOT_DATA;
}
// 系统数据
else if(CacheConstants.EDEN_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.EDEN_DATA).append(":");
type = PushSubType.EDEN_DATA;
} else {
// 如果都不是 则直接退出 不走缓存 // 如果都不是 则直接退出 不走缓存
return null; return null;
} }
// key 前缀
StringBuilder keyBuf = this.judgeCacheKeyBuf(aCache.name());
try { // 这里 只对 继承了 BaseEntity 的类做处理
// 这里 只对 继承了 BaseEntity 的类做处理 ApiWrapper apiWrapper = (ApiWrapper) returnValue;
ApiWrapper apiWrapper = (ApiWrapper) returnValue;
// key 存储ID // key 存储ID
String key = keyBuf.append(apiWrapper.getId()).toString(); String key = keyBuf.append(apiWrapper.getId()).toString();
ret = new CacheDataEntity(); CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name());
ret.setKey(key); // 存放数据
ret.setType(type); this.putCacheData(cacheDataEntities, ret);
ret.setCacheName(aCache.name());
return ret; return cacheDataEntities;
}catch (Exception e){
log.error(e.getMessage(),e);
}
} }
}catch (Exception e){ }catch (Exception e){
log.error(e.getMessage(),e); log.error(e.getMessage(),e);
@ -237,89 +232,67 @@ public class CacheDataAop {
return null; return null;
} }
// DEL 消息集合 // 消息集合
List<CacheDataEntity> cacheDataEntities = Lists.newArrayListWithCapacity(args.length); List<CacheDataEntity> cacheDataEntities = Lists.newArrayListWithCapacity(args.length);
// 报错不处理 // 报错不处理
try { try {
String methodName= point.getSignature().getName(); // 获得方法
Class<?> classTarget= point.getTarget().getClass(); Method objMethod = this.getMethod(point);
Class<?>[] par=((MethodSignature) point.getSignature()).getParameterTypes(); if(objMethod == null) return null;
Method objMethod = classTarget.getMethod(methodName, par);
// 获取注解参数 // 获取注解参数
HotDataDel aCache= objMethod.getAnnotation(HotDataDel.class); HotDataDel aCache= objMethod.getAnnotation(HotDataDel.class);
if(aCache != null){ if(aCache != null){
// 类型 // 获得缓存类型
PushSubType type; PushSubType type = this.judgeCacheType(aCache.name());
// key 前缀 if(type == null) {
StringBuilder keyBuf = new StringBuilder(PREFIX_NAME);
// 热点数据
if(CacheConstants.HOT_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.HOT_DATA).append(":");
type = PushSubType.HOT_DATA;
}
// 系统数据
else if(CacheConstants.EDEN_DATA.equals(aCache.name())){
keyBuf.append(CacheConstants.EDEN_DATA).append(":");
type = PushSubType.EDEN_DATA;
} else {
// 如果都不是 则直接退出 不走缓存 // 如果都不是 则直接退出 不走缓存
return null; return null;
} }
// key 前缀
try { StringBuilder keyBuf = this.judgeCacheKeyBuf(aCache.name());
// 处理数据 // 处理数据
for (Object arg : args) { for (Object arg : args) {
if (arg instanceof String) { if (arg instanceof String) {
// key 存储ID
String key = keyBuf.toString() + arg;
CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name());
// 存放数据
this.putCacheData(cacheDataEntities, ret);
} else if (arg instanceof String[]) {
String[] ids = (String[]) arg;
for (String id : ids) {
// key 存储ID // key 存储ID
String key = keyBuf.toString() + arg; String key = keyBuf.toString() + id;
CacheDataEntity ret = new CacheDataEntity(); CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name());
ret.setKey(key); // 存放数据
ret.setType(type); this.putCacheData(cacheDataEntities, ret);
ret.setCacheName(aCache.name()); }
cacheDataEntities.add(ret); } else if (arg instanceof ApiWrapper) {
} else if (arg instanceof String[]) { // key 存储ID
String[] ids = (String[]) arg; ApiWrapper apiWrapper = (ApiWrapper) arg;
for (String id : ids) { String key = keyBuf.toString() + apiWrapper.getId();
CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name());
// 存放数据
this.putCacheData(cacheDataEntities, ret);
} else if (arg instanceof Collection) {
try {
Collection<ApiWrapper> baseEntityList = (Collection<ApiWrapper>) arg;
for (ApiWrapper baseEntity : baseEntityList) {
// key 存储ID // key 存储ID
String key = keyBuf.toString() + id; String key = keyBuf.toString() + baseEntity.getId();
CacheDataEntity ret = new CacheDataEntity(); CacheDataEntity ret = new CacheDataEntity(key, type ,aCache.name());
ret.setKey(key); // 存放数据
ret.setType(type); this.putCacheData(cacheDataEntities, ret);
ret.setCacheName(aCache.name());
cacheDataEntities.add(ret);
}
} else if (arg instanceof ApiWrapper) {
// key 存储ID
ApiWrapper apiWrapper = (ApiWrapper) arg;
String key = keyBuf.toString() + apiWrapper.getId();
CacheDataEntity ret = new CacheDataEntity();
ret.setKey(key);
ret.setType(type);
ret.setCacheName(aCache.name());
cacheDataEntities.add(ret);
} else if (arg instanceof Collection) {
try {
Collection<ApiWrapper> baseEntityList = (Collection<ApiWrapper>) arg;
for (ApiWrapper baseEntity : baseEntityList) {
// key 存储ID
String key = keyBuf.toString() + baseEntity.getId();
CacheDataEntity ret = new CacheDataEntity();
ret.setKey(key);
ret.setType(type);
ret.setCacheName(aCache.name());
cacheDataEntities.add(ret);
}
}catch (Exception e){
log.error(e.getMessage(),e);
} }
}catch (Exception e){
log.error(e.getMessage(),e);
} }
} }
return cacheDataEntities;
}catch (Exception e){
log.error(e.getMessage(),e);
} }
return cacheDataEntities;
} }
}catch (Exception e){ }catch (Exception e){
log.error(e.getMessage(),e); log.error(e.getMessage(),e);
@ -327,4 +300,73 @@ public class CacheDataAop {
return null; return null;
} }
// =====================
/**
*
* @param point
* @return
*/
private Method getMethod(ProceedingJoinPoint point){
Method m = null;
try {
String methodName= point.getSignature().getName();
Class<?> classTarget= point.getTarget().getClass();
Class<?>[] par=((MethodSignature) point.getSignature()).getParameterTypes();
m = classTarget.getMethod(methodName, par);
}catch (Exception ignored){}
return m;
}
/**
*
* @param cacheDataList
* @param cacheData
*/
private void putCacheData(List<CacheDataEntity> cacheDataList, CacheDataEntity cacheData){
// 非法判断
if(CollUtil.isEmpty(cacheDataList)){
return;
}
cacheDataList.add(cacheData);
}
/**
* Key
* @param cacheName
* @return
*/
private StringBuilder judgeCacheKeyBuf(String cacheName){
// key 前缀
StringBuilder keyBuf = new StringBuilder(PREFIX_NAME);
// 热点数据
if(CacheConstants.HOT_DATA.equals(cacheName)){
keyBuf.append(CacheConstants.HOT_DATA).append(":");
}
// 系统数据
else if(CacheConstants.EDEN_DATA.equals(cacheName)){
keyBuf.append(CacheConstants.EDEN_DATA).append(":");
}
return keyBuf;
}
/**
*
* @param cacheName
* @return
*/
private PushSubType judgeCacheType(String cacheName){
PushSubType type = null;
// 热点数据
if(CacheConstants.HOT_DATA.equals(cacheName)){
type = PushSubType.HOT_DATA;
}
// 系统数据
else if(CacheConstants.EDEN_DATA.equals(cacheName)){
type = PushSubType.EDEN_DATA;
}
return type;
}
} }

@ -13,29 +13,27 @@
* License for the specific language governing permissions and limitations under * License for the specific language governing permissions and limitations under
* the License. * the License.
*/ */
package org.opsli.modulars.system.area.entity; package org.opsli.core.base.entity;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.opsli.core.base.entity.BaseEntity;
/** /**
* @BelongsProject: opsli-boot * @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.system.area.entity * @BelongsPackage: org.opsli.modulars.system.area.entity
* @Author: Parker * @Author: Parker
* @CreateTime: 2020-11-28 18:59:59 * @CreateTime: 2020-11-28 18:59:59
* @Description: * @Description: Tree
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class HasChildren{ public class HasChildren {
/** 父级主键 */ /** 父级主键 */
private String parentId; private String parentId;
/** 地域名称 */ /** 下级数量 */
private Integer count; private Integer count;

@ -25,6 +25,7 @@ import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.opsli.common.constants.CacheConstants; import org.opsli.common.constants.CacheConstants;
import org.opsli.common.utils.Props;
import org.opsli.core.aspect.CacheDataAop; import org.opsli.core.aspect.CacheDataAop;
import org.opsli.plugins.cache.EhCachePlugin; import org.opsli.plugins.cache.EhCachePlugin;
import org.opsli.plugins.redis.RedisPlugin; import org.opsli.plugins.redis.RedisPlugin;
@ -65,18 +66,27 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
@AutoConfigureAfter({RedisPlugin.class , EhCachePlugin.class}) @AutoConfigureAfter({RedisPlugin.class , EhCachePlugin.class})
public class CacheUtil { public class CacheUtil {
public static final String JSON_KEY = "data";
/** 空状态 key 前缀 */
private static final String NIL_FLAG_PREFIX = "opsli:nil:";
/** 热点数据缓存时间 秒 */ /** 热点数据缓存时间 秒 */
private static int ttlHotData = 60000; private static int ttlHotData = 60000;
/** Redis插件 */ /** Redis插件 */
private static RedisPlugin redisPlugin; private static RedisPlugin redisPlugin;
/** EhCache插件 */ /** EhCache插件 */
private static EhCachePlugin ehCachePlugin; private static EhCachePlugin ehCachePlugin;
/** Json key */
public static final String JSON_KEY = "data";
/** 空状态 key 前缀 */
private static final String NIL_FLAG_PREFIX;
/** 热点数据前缀 */
public static final String PREFIX_NAME;
static { static {
// 缓存前缀
Props props = new Props("application.yaml");
PREFIX_NAME = props.getStr("spring.cache-conf.prefix",CacheConstants.PREFIX_NAME) + ":";
NIL_FLAG_PREFIX = PREFIX_NAME + "nil:";
try { try {
// 读取配置信息 // 读取配置信息
CacheUtil.readPropertyXML(); CacheUtil.readPropertyXML();

@ -15,7 +15,10 @@
*/ */
package org.opsli.core.cache.pushsub.entity; package org.opsli.core.cache.pushsub.entity;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.opsli.core.cache.pushsub.enums.PushSubType; import org.opsli.core.cache.pushsub.enums.PushSubType;
/** /**
@ -26,6 +29,8 @@ import org.opsli.core.cache.pushsub.enums.PushSubType;
* @Description: Entity * @Description: Entity
*/ */
@Data @Data
@AllArgsConstructor
@NoArgsConstructor
public class CacheDataEntity { public class CacheDataEntity {
/** key */ /** key */
@ -37,4 +42,9 @@ public class CacheDataEntity {
/** 缓存名称 */ /** 缓存名称 */
private String cacheName; private String cacheName;
public static void main(String[] args) {
CacheDataEntity ret = new CacheDataEntity("123", PushSubType.EDEN_DATA, "12aaaa");
System.out.println(ToStringBuilder.reflectionToString(ret));
}
} }

@ -47,6 +47,11 @@ public enum MsgArgsType {
/** 菜单数据*/ /** 菜单数据*/
MENU_MODEL_DATA, MENU_MODEL_DATA,
/** 组织 用户ID */
ORG_USER_ID,
/** 组织 用户数据 */
ORG_USER_DATA,
/** 缓存数据Key */ /** 缓存数据Key */
CACHE_DATA_KEY, CACHE_DATA_KEY,
/** 缓存数据Value */ /** 缓存数据Value */

@ -33,6 +33,9 @@ public enum PushSubType {
/** 菜单数据 */ /** 菜单数据 */
MENU, MENU,
/** 组织数据 */
ORG,
/** 热点数据 */ /** 热点数据 */
HOT_DATA, HOT_DATA,

@ -31,7 +31,7 @@ import org.springframework.beans.factory.annotation.Autowired;
* @BelongsPackage: org.opsli.core.cache.pushsub.handler * @BelongsPackage: org.opsli.core.cache.pushsub.handler
* @Author: Parker * @Author: Parker
* @CreateTime: 2020-09-15 16:24 * @CreateTime: 2020-09-15 16:24
* @Description: * @Description:
*/ */
@Slf4j @Slf4j
public class MenuHandler implements RedisPushSubHandler{ public class MenuHandler implements RedisPushSubHandler{
@ -46,7 +46,7 @@ public class MenuHandler implements RedisPushSubHandler{
@Override @Override
public void handler(JSONObject msgJson) { public void handler(JSONObject msgJson) {
// 用户刷新 // 菜单刷新
this.menuHandler(msgJson); this.menuHandler(msgJson);
} }
@ -59,7 +59,7 @@ public class MenuHandler implements RedisPushSubHandler{
// 数据为空则不执行 // 数据为空则不执行
if(data == null) return; if(data == null) return;
// 获得用户ID 和 用户名 // 获得菜单编号
String menuCode = (String) msgJson.get(MsgArgsType.MENU_CODE.toString()); String menuCode = (String) msgJson.get(MsgArgsType.MENU_CODE.toString());
if(StringUtils.isEmpty(menuCode)){ if(StringUtils.isEmpty(menuCode)){
return; return;

@ -0,0 +1,76 @@
/**
* 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.cache.pushsub.handler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.common.constants.CacheConstants;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.core.utils.MenuUtil;
import org.opsli.core.utils.OrgUtil;
import org.opsli.plugins.cache.EhCachePlugin;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.handler
* @Author: Parker
* @CreateTime: 2020-09-15 16:24
* @Description:
*/
@Slf4j
public class OrgHandler implements RedisPushSubHandler{
@Autowired
EhCachePlugin ehCachePlugin;
@Override
public PushSubType getType() {
return PushSubType.ORG;
}
@Override
public void handler(JSONObject msgJson) {
// 用户刷新
this.orgHandler(msgJson);
}
/**
*
* @param msgJson
*/
private void orgHandler(JSONObject msgJson){
JSONObject data = msgJson.getJSONObject(MsgArgsType.ORG_USER_DATA.toString());
// 数据为空则不执行
if(data == null) return;
// 获得用户ID
String userId = (String) msgJson.get(MsgArgsType.ORG_USER_ID.toString());
if(StringUtils.isEmpty(userId)){
return;
}
// 先删除
ehCachePlugin.delete(CacheConstants.HOT_DATA, OrgUtil.PREFIX_CODE + userId);
// 清除空拦截
CacheUtil.delNilFlag(OrgUtil.PREFIX_CODE + userId);
}
}

@ -0,0 +1,61 @@
/**
* 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.cache.pushsub.msgs;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.experimental.Accessors;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.user.UserOrgRefModel;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.core.cache.pushsub.receiver.RedisPushSubReceiver;
import org.opsli.plugins.redis.pushsub.entity.BaseSubMessage;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.msgs
* @Author: Parker
* @CreateTime: 2020-09-15 16:50
* @Description:
*/
@Data
@Accessors(chain = true)
public final class OrgMsgFactory extends BaseSubMessage{
/** 通道 */
private static final String CHANNEL = RedisPushSubReceiver.BASE_CHANNEL+RedisPushSubReceiver.CHANNEL;
private OrgMsgFactory(){}
/**
* -
*/
public static BaseSubMessage createOrgMsg(UserOrgRefModel orgRefModel){
BaseSubMessage baseSubMessage = new BaseSubMessage();
// 数据
JSONObject jsonObj = new JSONObject();
jsonObj.put(MsgArgsType.ORG_USER_ID.toString(), orgRefModel.getUserId());
jsonObj.put(MsgArgsType.ORG_USER_DATA.toString(), orgRefModel);
// 用户
baseSubMessage.build(CHANNEL,PushSubType.ORG.toString(),jsonObj);
return baseSubMessage;
}
}

@ -18,7 +18,9 @@ package org.opsli.core.utils;
import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.Producer;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.opsli.api.web.system.dict.DictDetailApi; import org.opsli.api.web.system.dict.DictDetailApi;
import org.opsli.common.constants.CacheConstants;
import org.opsli.common.exception.TokenException; import org.opsli.common.exception.TokenException;
import org.opsli.common.utils.Props;
import org.opsli.core.msg.TokenMsg; import org.opsli.core.msg.TokenMsg;
import org.opsli.plugins.redis.RedisLockPlugins; import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.RedisPlugin; import org.opsli.plugins.redis.RedisPlugin;
@ -45,13 +47,20 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
public class CaptchaUtil{ public class CaptchaUtil{
/** 缓存前缀 */ /** 缓存前缀 */
private static final String PREFIX = "opsli:temp:captcha:"; private static final String PREFIX = "temp:captcha:";
/** 默认验证码保存 5 分钟 */ /** 默认验证码保存 5 分钟 */
private static final int TIME_OUT = 300; private static final int TIME_OUT = 300;
/** Redis插件 */ /** Redis插件 */
private static RedisPlugin redisPlugin; private static RedisPlugin redisPlugin;
/** 谷歌验证码 */ /** 谷歌验证码 */
private static Producer producer; private static Producer producer;
/** 热点数据前缀 */
public static final String PREFIX_NAME;
static{
// 缓存前缀
Props props = new Props("application.yaml");
PREFIX_NAME = props.getStr("spring.cache-conf.prefix", CacheConstants.PREFIX_NAME) + ":";
}
/** /**
* *
@ -66,7 +75,7 @@ public class CaptchaUtil{
//生成文字验证码 //生成文字验证码
String code = producer.createText(); String code = producer.createText();
boolean ret = redisPlugin.put(PREFIX + uuid, code, TIME_OUT); boolean ret = redisPlugin.put(PREFIX_NAME + PREFIX + uuid, code, TIME_OUT);
if(ret){ if(ret){
return producer.createImage(code); return producer.createImage(code);
@ -84,14 +93,14 @@ public class CaptchaUtil{
if(StringUtils.isEmpty(uuid)) return false; if(StringUtils.isEmpty(uuid)) return false;
// 验证码 // 验证码
String codeTemp = (String) redisPlugin.get(PREFIX + uuid); String codeTemp = (String) redisPlugin.get(PREFIX_NAME + PREFIX + uuid);
if(StringUtils.isEmpty(codeTemp)){ if(StringUtils.isEmpty(codeTemp)){
throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_NULL); throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_NULL);
} }
// 删除验证码 // 删除验证码
//redisPlugin.del(PREFIX + uuid); //redisPlugin.del(PREFIX_NAME + PREFIX + uuid);
return codeTemp.equalsIgnoreCase(code); return codeTemp.equalsIgnoreCase(code);
} }
@ -106,7 +115,7 @@ public class CaptchaUtil{
if(StringUtils.isEmpty(uuid)) return false; if(StringUtils.isEmpty(uuid)) return false;
//删除验证码 //删除验证码
return redisPlugin.del(PREFIX + uuid); return redisPlugin.del(PREFIX_NAME + PREFIX + uuid);
} }

@ -23,6 +23,7 @@ import org.opsli.api.web.system.user.UserApi;
import org.opsli.api.wrapper.system.menu.MenuModel; import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.core.cache.local.CacheUtil; import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.MenuMsgFactory; import org.opsli.core.cache.pushsub.msgs.MenuMsgFactory;
import org.opsli.core.cache.pushsub.msgs.OrgMsgFactory;
import org.opsli.plugins.redis.RedisLockPlugins; import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.RedisPlugin; import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock; import org.opsli.plugins.redis.lock.RedisLock;
@ -58,7 +59,7 @@ public class MenuUtil {
/** Redis分布式锁 */ /** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins; private static RedisLockPlugins redisLockPlugins;
/** 用户Service */ /** 菜单 Api */
private static MenuApi menuApi; private static MenuApi menuApi;
@ -139,13 +140,17 @@ public class MenuUtil {
} }
MenuModel menuModel = CacheUtil.get(PREFIX_CODE + menu.getMenuCode(), MenuModel.class); MenuModel menuModel = CacheUtil.get(PREFIX_CODE + menu.getMenuCode(), MenuModel.class);
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + menu.getMenuCode());
// 只要不为空 则执行刷新 // 只要不为空 则执行刷新
if (menuModel != null){ if (hasNilFlag){
// 先删除
CacheUtil.del(PREFIX_CODE + menu.getMenuCode());
// 清除空拦截 // 清除空拦截
CacheUtil.delNilFlag(PREFIX_CODE + menu.getMenuCode()); CacheUtil.delNilFlag(PREFIX_CODE + menu.getMenuCode());
}
if(menuModel != null){
// 先删除
CacheUtil.del(PREFIX_CODE + menu.getMenuCode());
// 发送通知消息 // 发送通知消息
redisPlugin.sendMessage( redisPlugin.sendMessage(

@ -0,0 +1,183 @@
/**
* 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.menu.MenuApi;
import org.opsli.api.web.system.user.UserApi;
import org.opsli.api.wrapper.system.menu.MenuModel;
import org.opsli.api.wrapper.system.user.UserOrgRefModel;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.MenuMsgFactory;
import org.opsli.core.cache.pushsub.msgs.OrgMsgFactory;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.utils
* @Author: Parker
* @CreateTime: 2020-09-19 20:03
* @Description:
*/
@Slf4j
@Order(UTIL_ORDER)
@Component
@AutoConfigureAfter({RedisPlugin.class , RedisLockPlugins.class, UserApi.class})
@Lazy(false)
public class OrgUtil {
/** 前缀 */
public static final String PREFIX_CODE = "org:userId:";
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins;
/** 用户 Api */
private static UserApi userApi;
/**
* userId
* @param userId
* @return
*/
public static UserOrgRefModel getOrgByUserId(String userId){
// 先从缓存里拿
UserOrgRefModel orgRefModel = CacheUtil.get(PREFIX_CODE + userId, UserOrgRefModel.class);
if (orgRefModel != null){
return orgRefModel;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + userId);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_CODE + userId)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
orgRefModel = CacheUtil.get(PREFIX_CODE + userId, UserOrgRefModel.class);
if (orgRefModel != null){
return orgRefModel;
}
// 查询数据库
ResultVo<UserOrgRefModel> resultVo = userApi.getOrgInfoByUserId(userId);
if(resultVo.isSuccess()){
orgRefModel = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_CODE + userId, orgRefModel);
}
}catch (Exception e){
log.error(e.getMessage(),e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
redisLock = null;
}
if(orgRefModel == null){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_CODE + userId);
return null;
}
return orgRefModel;
}
// ============== 刷新缓存 ==============
/**
* -
* @param userId
* @return
*/
public static void refreshMenu(String userId){
if(StringUtils.isEmpty(userId)){
return;
}
UserOrgRefModel orgRefModel = CacheUtil.get(PREFIX_CODE + userId, UserOrgRefModel.class);
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE + userId);
// 只要不为空 则执行刷新
if (hasNilFlag){
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_CODE + userId);
}
if(orgRefModel != null){
// 先删除
CacheUtil.del(PREFIX_CODE + userId);
// 发送通知消息
redisPlugin.sendMessage(
OrgMsgFactory.createOrgMsg(orgRefModel)
);
}
}
// =====================================
@Autowired
public void setRedisPlugin(RedisPlugin redisPlugin) {
OrgUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) {
OrgUtil.redisLockPlugins = redisLockPlugins;
}
@Autowired
public void setUserApi(UserApi userApi) {
OrgUtil.userApi = userApi;
}
}

@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.crypto.hash.Md5Hash;
import org.opsli.api.base.result.ResultVo; import org.opsli.api.base.result.ResultVo;
import org.opsli.api.wrapper.system.user.UserModel; import org.opsli.api.wrapper.system.user.UserModel;
import org.opsli.common.constants.CacheConstants;
import org.opsli.common.constants.SignConstants; import org.opsli.common.constants.SignConstants;
import org.opsli.common.constants.TokenConstants; import org.opsli.common.constants.TokenConstants;
import org.opsli.common.exception.ServiceException; import org.opsli.common.exception.ServiceException;
@ -62,11 +63,11 @@ public class UserTokenUtil {
/** token 缓存名 */ /** token 缓存名 */
public static final String TOKEN_NAME = TokenConstants.ACCESS_TOKEN; public static final String TOKEN_NAME = TokenConstants.ACCESS_TOKEN;
/** 缓存前缀 */ /** 缓存前缀 */
private static final String PREFIX = "opsli:ticket:"; private static final String TICKET_PREFIX;
/** 账号失败次数 */ /** 账号失败次数 */
public static final String ACCOUNT_SLIP_COUNT_PREFIX = "opsli:account:slip:count:"; public static final String ACCOUNT_SLIP_COUNT_PREFIX;
/** 账号失败锁定KEY */ /** 账号失败锁定KEY */
public static final String ACCOUNT_SLIP_LOCK_PREFIX = "opsli:account:slip:lock:"; public static final String ACCOUNT_SLIP_LOCK_PREFIX;
/** 账号失败阈值 */ /** 账号失败阈值 */
public static final int ACCOUNT_SLIP_COUNT; public static final int ACCOUNT_SLIP_COUNT;
/** 账号失败N次后弹出验证码 */ /** 账号失败N次后弹出验证码 */
@ -77,15 +78,24 @@ public class UserTokenUtil {
/** Redis插件 */ /** Redis插件 */
private static RedisPlugin redisPlugin; private static RedisPlugin redisPlugin;
/** 热点数据前缀 */
public static final String PREFIX_NAME;
static{
static { // 缓存前缀
Props props = new Props("application.yaml"); Props props = new Props("application.yaml");
PREFIX_NAME = props.getStr("spring.cache-conf.prefix", CacheConstants.PREFIX_NAME) + ":";
TICKET_PREFIX = PREFIX_NAME + "ticket:";
ACCOUNT_SLIP_COUNT_PREFIX = PREFIX_NAME + "account:slip:count:";
ACCOUNT_SLIP_LOCK_PREFIX = PREFIX_NAME + "account:slip:lock:";
// 配置数据
ACCOUNT_SLIP_COUNT = props.getInt("opsli.login.slip-count", 5); ACCOUNT_SLIP_COUNT = props.getInt("opsli.login.slip-count", 5);
ACCOUNT_SLIP_VERIFY_COUNT = props.getInt("opsli.login.slip-verify-count", 3); ACCOUNT_SLIP_VERIFY_COUNT = props.getInt("opsli.login.slip-verify-count", 3);
ACCOUNT_SLIP_LOCK_SPEED = props.getInt("opsli.login.slip-lock-speed", 300); ACCOUNT_SLIP_LOCK_SPEED = props.getInt("opsli.login.slip-lock-speed", 300);
} }
/** /**
* user Token * user Token
* @param user * @param user
@ -121,7 +131,7 @@ public class UserTokenUtil {
// token 缓存真实失效时间 建议大于 最终时间 -- 多加了20分钟的失效时间 // token 缓存真实失效时间 建议大于 最终时间 -- 多加了20分钟的失效时间
// 在redis存一份 token 是为了防止 认为造假 // 在redis存一份 token 是为了防止 认为造假
boolean tokenFlag = redisPlugin.put(PREFIX + signTokenHex, endTimestamp, expire + 20); boolean tokenFlag = redisPlugin.put(TICKET_PREFIX + signTokenHex, endTimestamp, expire + 20);
if(tokenFlag){ if(tokenFlag){
map.put("token", signToken); map.put("token", signToken);
map.put("expire", endTimestamp); map.put("expire", endTimestamp);
@ -177,7 +187,7 @@ public class UserTokenUtil {
// 生成MD5 16进制码 用于缩减存储 // 生成MD5 16进制码 用于缩减存储
String signTokenHex = new Md5Hash(token).toHex(); String signTokenHex = new Md5Hash(token).toHex();
redisPlugin.del(PREFIX + signTokenHex); redisPlugin.del(TICKET_PREFIX + signTokenHex);
// 删除相关信息 // 删除相关信息
String userId = getUserIdByToken(token); String userId = getUserIdByToken(token);
@ -209,7 +219,7 @@ public class UserTokenUtil {
// 2. 校验当前缓存中token是否失效 // 2. 校验当前缓存中token是否失效
// 生成MD5 16进制码 用于缩减存储 // 生成MD5 16进制码 用于缩减存储
String signTokenHex = new Md5Hash(token).toHex(); String signTokenHex = new Md5Hash(token).toHex();
Long endTimestamp = (Long) redisPlugin.get(PREFIX + signTokenHex); Long endTimestamp = (Long) redisPlugin.get(TICKET_PREFIX + signTokenHex);
if(endTimestamp == null){ if(endTimestamp == null){
return false; return false;
} }

@ -29,6 +29,7 @@ import org.opsli.common.api.TokenThreadLocal;
import org.opsli.common.exception.TokenException; import org.opsli.common.exception.TokenException;
import org.opsli.common.utils.Props; import org.opsli.common.utils.Props;
import org.opsli.core.cache.local.CacheUtil; import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.MenuMsgFactory;
import org.opsli.core.cache.pushsub.msgs.UserMsgFactory; import org.opsli.core.cache.pushsub.msgs.UserMsgFactory;
import org.opsli.core.msg.TokenMsg; import org.opsli.core.msg.TokenMsg;
import org.opsli.plugins.redis.RedisLockPlugins; import org.opsli.plugins.redis.RedisLockPlugins;
@ -537,6 +538,16 @@ public class UserUtil {
UserModel userModelByUsername = CacheUtil.get(PREFIX_USERNAME + user.getUsername(), UserModel userModelByUsername = CacheUtil.get(PREFIX_USERNAME + user.getUsername(),
UserModel.class); UserModel.class);
boolean hasNilFlagById = CacheUtil.hasNilFlag(PREFIX_ID + user.getId());
boolean hasNilFlagByName = CacheUtil.hasNilFlag(PREFIX_USERNAME + user.getUsername());
// 只要有一个不为空 则执行刷新
if (hasNilFlagById || hasNilFlagByName){
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_ID + user.getId());
CacheUtil.delNilFlag(PREFIX_USERNAME + user.getUsername());
}
// 只要有一个不为空 则执行刷新 // 只要有一个不为空 则执行刷新
if (userModelById != null || userModelByUsername != null){ if (userModelById != null || userModelByUsername != null){
// 先删除 // 先删除
@ -562,17 +573,24 @@ public class UserUtil {
public static void refreshUserRoles(String userId){ public static void refreshUserRoles(String userId){
try { try {
Object obj = CacheUtil.get(PREFIX_ID_ROLES + userId); Object obj = CacheUtil.get(PREFIX_ID_ROLES + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_ROLES + userId);
// 只要不为空 则执行刷新
if (hasNilFlag){
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_ID_ROLES + userId);
}
if(obj != null){ if(obj != null){
// 先删除 // 先删除
CacheUtil.del(PREFIX_ID_ROLES + userId); CacheUtil.del(PREFIX_ID_ROLES + userId);
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_ID_ROLES + userId);
// 发送通知消息 // 发送通知消息
redisPlugin.sendMessage( redisPlugin.sendMessage(
UserMsgFactory.createUserRolesMsg(userId, null) UserMsgFactory.createUserRolesMsg(userId, null)
); );
} }
}catch (Exception e){ }catch (Exception e){
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
@ -586,11 +604,17 @@ public class UserUtil {
public static void refreshUserAllPerms(String userId){ public static void refreshUserAllPerms(String userId){
try { try {
Object obj = CacheUtil.get(PREFIX_ID_PERMISSIONS + userId); Object obj = CacheUtil.get(PREFIX_ID_PERMISSIONS + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_PERMISSIONS + userId);
// 只要不为空 则执行刷新
if (hasNilFlag){
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_ID_PERMISSIONS + userId);
}
if(obj != null){ if(obj != null){
// 先删除 // 先删除
CacheUtil.del(PREFIX_ID_PERMISSIONS + userId); CacheUtil.del(PREFIX_ID_PERMISSIONS + userId);
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_ID_PERMISSIONS + userId);
// 发送通知消息 // 发送通知消息
redisPlugin.sendMessage( redisPlugin.sendMessage(
@ -610,17 +634,24 @@ public class UserUtil {
public static void refreshUserMenus(String userId){ public static void refreshUserMenus(String userId){
try { try {
Object obj = CacheUtil.get(PREFIX_ID_MENUS + userId); Object obj = CacheUtil.get(PREFIX_ID_MENUS + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_MENUS + userId);
// 只要不为空 则执行刷新
if (hasNilFlag){
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_ID_MENUS + userId);
}
if(obj != null){ if(obj != null){
// 先删除 // 先删除
CacheUtil.del(PREFIX_ID_MENUS + userId); CacheUtil.del(PREFIX_ID_MENUS + userId);
// 清除空拦截
CacheUtil.delNilFlag(PREFIX_ID_MENUS + userId);
// 发送通知消息 // 发送通知消息
redisPlugin.sendMessage( redisPlugin.sendMessage(
UserMsgFactory.createUserMenusMsg(userId, null) UserMsgFactory.createUserMenusMsg(userId, null)
); );
} }
}catch (Exception e){ }catch (Exception e){
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }

@ -17,6 +17,10 @@ opsli:
- sys_tenant - sys_tenant
- sys_user - sys_user
- sys_user_role_ref - sys_user_role_ref
- sys_area
- sys_org
- sys_org_user_ref
# 排除字段 # 排除字段
exclude-fields: exclude-fields:

@ -16,6 +16,9 @@
package org.opsli.plugins.redis.lock; package org.opsli.plugins.redis.lock;
import org.opsli.common.constants.CacheConstants;
import org.opsli.common.utils.Props;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
/** /**
@ -27,7 +30,17 @@ import java.util.concurrent.atomic.AtomicInteger;
*/ */
public class RedisLock { public class RedisLock {
private static final String LOCK_PREFIX = "opsli:lock:"; private static final String LOCK_PREFIX;
/** 热点数据前缀 */
public static final String PREFIX_NAME;
static {
// 缓存前缀
Props props = new Props("application.yaml");
PREFIX_NAME = props.getStr("spring.cache-conf.prefix", CacheConstants.PREFIX_NAME) + ":";
LOCK_PREFIX = PREFIX_NAME + "lock:";
}
/** 锁名称 */ /** 锁名称 */
private String lockName; private String lockName;
@ -44,8 +57,6 @@ public class RedisLock {
/** 线程锁 */ /** 线程锁 */
private AtomicInteger atomicInteger; private AtomicInteger atomicInteger;
/** /**
* *
*/ */

@ -66,7 +66,18 @@ spring:
# 默认编码 # 默认编码
default-encoding: UTF-8 default-encoding: UTF-8
# 一级缓存 ---- redis 配置 # 缓存配置项
cache-conf:
# 前缀
prefix: opsli
# 一级缓存 ---- EhCache 配置
cache:
# 开启 是否启用本地缓存
enable: true
# 加载配置文件
jcache:
config: classpath:config/ehcache-opsli.xml
# 二级缓存 ---- Redis 配置
redis: redis:
# 开启消息订阅 # 开启消息订阅
pushsub: pushsub:
@ -78,13 +89,6 @@ spring:
max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
min-idle: 0 #最小等待连接中的数量,设 0 为没有限制 min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
shutdown-timeout: 100ms shutdown-timeout: 100ms
# 二级缓存 ---- EhCache 配置
cache:
# 开启 是否启用本地缓存
enable: true
# 加载配置文件
jcache:
config: classpath:config/ehcache-opsli.xml
# 数据库配置 # 数据库配置
datasource: datasource:

Loading…
Cancel
Save