From 56c44acd11c405e7a7c82b3537d129fb2cabe155 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 25 Feb 2023 18:00:05 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=94=B9=E9=80=A0=EF=BC=9ARo?= =?UTF-8?q?leMenu=20=E4=BD=BF=E7=94=A8=20Redis=20=E4=BD=9C=E4=B8=BA?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dal/mysql/permission/RoleMenuMapper.java | 8 +- .../system/dal/redis/RedisKeyConstants.java | 8 ++ .../permission/RoleMenuRefreshConsumer.java | 29 ------ .../permission/RoleMenuRefreshMessage.java | 21 ----- .../permission/PermissionProducer.java | 26 ------ .../service/permission/PermissionService.java | 17 +++- .../permission/PermissionServiceImpl.java | 92 ++++--------------- 7 files changed, 48 insertions(+), 153 deletions(-) delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleMenuRefreshConsumer.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleMenuRefreshMessage.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java index df77b646dd..ec62e44670 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.tenant.core.db.dynamic.TenantDS; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -9,9 +10,10 @@ import org.springframework.stereotype.Repository; import java.util.Collection; import java.util.List; +import java.util.Set; @Mapper -// TODO 芋艿:@TenantDS +@TenantDS public interface RoleMenuMapper extends BaseMapperX { default List selectListByRoleId(Long roleId) { @@ -22,6 +24,10 @@ public interface RoleMenuMapper extends BaseMapperX { return selectList(RoleMenuDO::getRoleId, roleIds); } + default List selectListByMenuId(Long menuId) { + return selectList(RoleMenuDO::getMenuId, menuId); + } + default void deleteListByRoleIdAndMenuIds(Long roleId, Collection menuIds) { delete(new LambdaQueryWrapper() .eq(RoleMenuDO::getRoleId, roleId) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java index d3cfc802bf..93ba3f9729 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java @@ -42,4 +42,12 @@ public interface RedisKeyConstants { */ String USER_ROLE_ID = "user_role_id"; + /** + * 拥有指定菜单的角色编号的缓存 + * + * KEY 格式:user_role_ids::{menuId} + * 数据类型:String 角色编号集合 + */ + String MENU_ROLE_ID = "menu_role_id"; + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleMenuRefreshConsumer.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleMenuRefreshConsumer.java deleted file mode 100644 index d9f0e92208..0000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/permission/RoleMenuRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.system.mq.consumer.permission; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.module.system.mq.message.permission.RoleMenuRefreshMessage; -import cn.iocoder.yudao.module.system.service.permission.PermissionService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link RoleMenuRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class RoleMenuRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private PermissionService permissionService; - - @Override - public void onMessage(RoleMenuRefreshMessage message) { - log.info("[onMessage][收到 Role 与 Menu 的关联刷新消息]"); - permissionService.initLocalCache(); - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleMenuRefreshMessage.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleMenuRefreshMessage.java deleted file mode 100644 index 0982775bc6..0000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/permission/RoleMenuRefreshMessage.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.system.mq.message.permission; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 角色与菜单数据刷新 Message - * - * @author 芋道源码 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class RoleMenuRefreshMessage extends AbstractChannelMessage { - - @Override - public String getChannel() { - return "system.role-menu.refresh"; - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java deleted file mode 100644 index 612368d742..0000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/permission/PermissionProducer.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.system.mq.producer.permission; - -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; -import cn.iocoder.yudao.module.system.mq.message.permission.RoleMenuRefreshMessage; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * Permission 权限相关消息的 Producer - */ -@Component -public class PermissionProducer { - - @Resource - private RedisMQTemplate redisMQTemplate; - - /** - * 发送 {@link RoleMenuRefreshMessage} 消息 - */ - public void sendRoleMenuRefreshMessage() { - RoleMenuRefreshMessage message = new RoleMenuRefreshMessage(); - redisMQTemplate.send(message); - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java index 065d9a6e22..5322e5b42b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionService.java @@ -16,10 +16,7 @@ import static java.util.Collections.singleton; */ public interface PermissionService { - /** - * 初始化权限的本地缓存 - */ - void initLocalCache(); + // ========== 角色-菜单的相关方法 ========== /** * 获得角色拥有的菜单编号集合 @@ -39,6 +36,14 @@ public interface PermissionService { */ Set getRoleMenuListByRoleId(Collection roleIds); + /** + * 获得拥有指定菜单的角色编号数组,从缓存中获取 + * + * @param menuId 菜单编号 + * @return 角色编号数组 + */ + Set getMenuRoleIdListByMenuIdFromCache(Long menuId); + /** * 获得拥有多个角色的用户编号集合 * @@ -134,4 +139,8 @@ public interface PermissionService { */ DeptDataPermissionRespDTO getDeptDataPermission(Long userId); + // ========== 用户-角色的相关方法 ========== + + // ========== 用户-部门的相关方法 ========== + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java index 0e82b8e431..422899713c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; @@ -19,26 +18,20 @@ import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMenuMapper; import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; -import cn.iocoder.yudao.module.system.mq.producer.permission.PermissionProducer; import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.Multimap; import com.google.common.collect.Sets; -import lombok.Getter; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.support.TransactionSynchronization; -import org.springframework.transaction.support.TransactionSynchronizationManager; -import javax.annotation.PostConstruct; import javax.annotation.Resource; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.function.Supplier; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @@ -53,17 +46,6 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString @Slf4j public class PermissionServiceImpl implements PermissionService { - /** - * 菜单编号与角色编号的缓存映射 - * key:菜单编号 - * value:角色编号的数组 - * - * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 - */ - @Getter - @Setter // 单元测试需要 - private volatile Multimap menuRoleCache; - @Resource private RoleMenuMapper roleMenuMapper; @Resource @@ -78,33 +60,6 @@ public class PermissionServiceImpl implements PermissionService { @Resource private AdminUserService userService; - @Resource - private PermissionProducer permissionProducer; - - @Override - @PostConstruct - public void initLocalCache() { - initLocalCacheForRoleMenu(); - } - - /** - * 刷新 RoleMenu 本地缓存 - */ - @VisibleForTesting - void initLocalCacheForRoleMenu() { - // 注意:忽略自动多租户,因为要全局初始化缓存 - TenantUtils.executeIgnore(() -> { - // 第一步:查询数据 - List roleMenus = roleMenuMapper.selectList(); - log.info("[initLocalCacheForRoleMenu][缓存角色与菜单,数量为:{}]", roleMenus.size()); - - // 第二步:构建缓存 - ImmutableMultimap.Builder menuRoleCacheBuilder = ImmutableMultimap.builder(); - roleMenus.forEach(roleMenuDO -> menuRoleCacheBuilder.put(roleMenuDO.getMenuId(), roleMenuDO.getRoleId())); - menuRoleCache = menuRoleCacheBuilder.build(); - }); - } - @Override public Set getRoleMenuListByRoleId(Collection roleIds) { // 如果是管理员的情况下,获取全部菜单编号 @@ -115,6 +70,12 @@ public class PermissionServiceImpl implements PermissionService { return convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId); } + @Override + @Cacheable(value = RedisKeyConstants.MENU_ROLE_ID, key = "#menuId") + public Set getMenuRoleIdListByMenuIdFromCache(Long menuId) { + return convertSet(roleMenuMapper.selectListByMenuId(menuId), RoleMenuDO::getRoleId); + } + @Override @Transactional(rollbackFor = Exception.class) public void assignRoleMenu(Long roleId, Set menuIds) { @@ -135,15 +96,6 @@ public class PermissionServiceImpl implements PermissionService { if (!CollectionUtil.isEmpty(deleteMenuIds)) { roleMenuMapper.deleteListByRoleIdAndMenuIds(roleId, deleteMenuIds); } - // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了 - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - - @Override - public void afterCommit() { - permissionProducer.sendRoleMenuRefreshMessage(); - } - - }); } @Override @@ -215,22 +167,11 @@ public class PermissionServiceImpl implements PermissionService { } @Override - @Transactional(rollbackFor = Exception.class) public void processMenuDeleted(Long menuId) { roleMenuMapper.deleteListByMenuId(menuId); - // 发送刷新消息. 注意,需要事务提交后,在进行发送刷新消息。不然 db 还未提交,结果缓存先刷新了 - TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { - - @Override - public void afterCommit() { - permissionProducer.sendRoleMenuRefreshMessage(); - } - - }); } @Override - @Transactional(rollbackFor = Exception.class) public void processUserDeleted(Long userId) { userRoleMapper.deleteListByUserId(userId); } @@ -274,10 +215,17 @@ public class PermissionServiceImpl implements PermissionService { return false; } - // 获得是否拥有该权限,任一一个 + // 判断是否有权限 Set roleIds = convertSet(roles, RoleDO::getId); - return menuList.stream().anyMatch(menu -> CollUtil.containsAny(roleIds, - menuRoleCache.get(menu.getId()))); + for (MenuDO menu : menuList) { + // 拥有该角色的菜单编号数组 + Set menuRoleIds = getSelf().getMenuRoleIdListByMenuIdFromCache(menu.getId()); + // 如果有交集,说明有权限 + if (CollUtil.containsAny(menuRoleIds, roleIds)) { + return true; + } + } + return false; } @Override