parent
e98b06e7fe
commit
60fa1c3bfc
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue