fix(system/role): 修复角色菜单权限缓存未清理错误,优化角色菜单缓存逻辑

Closes #IBNENK
This commit is contained in:
2025-02-27 20:02:53 +08:00
parent 65941c1ee4
commit 0a62f81ad7
9 changed files with 50 additions and 47 deletions

View File

@@ -42,9 +42,9 @@ public class CacheConstants {
public static final String USER_KEY_PREFIX = "USER" + DELIMITER;
/**
* 菜单缓存键前缀
* 角色菜单缓存键前缀
*/
public static final String MENU_KEY_PREFIX = "MENU" + DELIMITER;
public static final String ROLE_MENU_KEY_PREFIX = "ROLE_MENU" + DELIMITER;
/**
* 字典缓存键前缀

View File

@@ -17,6 +17,7 @@
package top.continew.admin.common.context;
import lombok.Data;
import lombok.NoArgsConstructor;
import top.continew.admin.common.enums.DataScopeEnum;
import java.io.Serial;
@@ -29,6 +30,7 @@ import java.io.Serializable;
* @since 2023/3/7 22:08
*/
@Data
@NoArgsConstructor
public class RoleContext implements Serializable {
@Serial
@@ -48,4 +50,10 @@ public class RoleContext implements Serializable {
* 数据权限
*/
private DataScopeEnum dataScope;
public RoleContext(Long id, String code, DataScopeEnum dataScope) {
this.id = id;
this.code = code;
this.dataScope = dataScope;
}
}

View File

@@ -32,6 +32,7 @@ import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.auth.model.resp.RouteResp;
import top.continew.admin.auth.service.AuthService;
import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.common.context.RoleContext;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.system.enums.MenuTypeEnum;
import top.continew.admin.system.model.resp.ClientResp;
@@ -86,16 +87,16 @@ public class AuthServiceImpl implements AuthService {
@Override
public List<RouteResp> buildRouteTree(Long userId) {
Set<String> roleCodeSet = roleService.listCodeByUserId(userId);
if (CollUtil.isEmpty(roleCodeSet)) {
Set<RoleContext> roleSet = roleService.listByUserId(userId);
if (CollUtil.isEmpty(roleSet)) {
return new ArrayList<>(0);
}
// 查询菜单列表
Set<MenuResp> menuSet = new LinkedHashSet<>();
if (roleCodeSet.contains(SysConstants.SUPER_ROLE_CODE)) {
menuSet.addAll(menuService.listAll());
if (roleSet.stream().anyMatch(r -> SysConstants.SUPER_ROLE_ID.equals(r.getId()))) {
menuSet.addAll(menuService.listByRoleId(SysConstants.SUPER_ROLE_ID));
} else {
roleCodeSet.forEach(roleCode -> menuSet.addAll(menuService.listByRoleCode(roleCode)));
roleSet.forEach(r -> menuSet.addAll(menuService.listByRoleId(r.getId())));
}
List<MenuResp> menuList = menuSet.stream().filter(m -> !MenuTypeEnum.BUTTON.equals(m.getType())).toList();
if (CollUtil.isEmpty(menuList)) {

View File

@@ -40,10 +40,10 @@ public interface MenuMapper extends BaseMapper<MenuDO> {
Set<String> selectPermissionByUserId(@Param("userId") Long userId);
/**
* 根据角色编码查询
* 根据角色 ID 查询
*
* @param roleCode 角色编码
* @param roleId 角色 ID
* @return 菜单列表
*/
List<MenuDO> selectListByRoleCode(@Param("roleCode") String roleCode);
List<MenuDO> selectListByRoleId(@Param("roleId") Long roleId);
}

View File

@@ -34,13 +34,6 @@ import java.util.Set;
*/
public interface MenuService extends BaseService<MenuResp, MenuResp, MenuQuery, MenuReq>, IService<MenuDO> {
/**
* 查询全部菜单
*
* @return 菜单列表
*/
List<MenuResp> listAll();
/**
* 根据用户 ID 查询
*
@@ -50,10 +43,10 @@ public interface MenuService extends BaseService<MenuResp, MenuResp, MenuQuery,
Set<String> listPermissionByUserId(Long userId);
/**
* 根据角色编码查询
* 根据角色 ID 查询
*
* @param roleCode 角色编码
* @param roleId 角色 ID
* @return 菜单列表
*/
List<MenuResp> listByRoleCode(String roleCode);
List<MenuResp> listByRoleId(Long roleId);
}

View File

@@ -23,6 +23,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.system.enums.MenuTypeEnum;
import top.continew.admin.system.mapper.MenuMapper;
@@ -62,7 +63,7 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
if (MenuTypeEnum.DIR.equals(req.getType())) {
req.setComponent(StrUtil.blankToDefault(req.getComponent(), "Layout"));
}
RedisUtils.deleteByPattern(CacheConstants.MENU_KEY_PREFIX + StringConstants.ASTERISK);
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
return super.add(req);
}
@@ -78,7 +79,7 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
MenuDO oldMenu = super.getById(id);
CheckUtils.throwIfNotEqual(req.getType(), oldMenu.getType(), "不允许修改菜单类型");
super.update(req, id);
RedisUtils.deleteByPattern(CacheConstants.MENU_KEY_PREFIX + StringConstants.ASTERISK);
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
}
@Override
@@ -86,13 +87,7 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
public void delete(List<Long> ids) {
baseMapper.lambdaUpdate().in(MenuDO::getParentId, ids).remove();
super.delete(ids);
RedisUtils.deleteByPattern(CacheConstants.MENU_KEY_PREFIX + StringConstants.ASTERISK);
}
@Override
@Cached(key = "'ALL'", name = CacheConstants.MENU_KEY_PREFIX)
public List<MenuResp> listAll() {
return super.list(new MenuQuery(DisEnableStatusEnum.ENABLE), null);
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
}
@Override
@@ -101,9 +96,12 @@ public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuRes
}
@Override
@Cached(key = "#roleCode", name = CacheConstants.MENU_KEY_PREFIX)
public List<MenuResp> listByRoleCode(String roleCode) {
List<MenuDO> menuList = baseMapper.selectListByRoleCode(roleCode);
@Cached(key = "#roleId", name = CacheConstants.ROLE_MENU_KEY_PREFIX)
public List<MenuResp> listByRoleId(Long roleId) {
if (SysConstants.SUPER_ROLE_ID.equals(roleId)) {
return super.list(new MenuQuery(DisEnableStatusEnum.ENABLE), null);
}
List<MenuDO> menuList = baseMapper.selectListByRoleId(roleId);
List<MenuResp> list = BeanUtil.copyToList(menuList, MenuResp.class);
list.forEach(super::fill);
return list;

View File

@@ -18,7 +18,6 @@ package top.continew.admin.system.service.impl;
import cn.crane4j.annotation.ContainerMethod;
import cn.crane4j.annotation.MappingType;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alicp.jetcache.anno.CacheInvalidate;
@@ -45,7 +44,10 @@ import top.continew.admin.system.service.*;
import top.continew.starter.core.validation.CheckUtils;
import top.continew.starter.extension.crud.service.BaseServiceImpl;
import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -79,7 +81,6 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
@Override
@Transactional(rollbackFor = Exception.class)
@CacheInvalidate(key = "#req.code == 'admin' ? 'ALL' : #req.code", name = CacheConstants.MENU_KEY_PREFIX)
public void update(RoleReq req, Long id) {
String name = req.getName();
CheckUtils.throwIf(this.isNameExists(name, id), "修改失败,[{}] 已存在", name);
@@ -120,6 +121,7 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
@Override
@Transactional(rollbackFor = Exception.class)
@CacheInvalidate(key = "#id", name = CacheConstants.ROLE_MENU_KEY_PREFIX)
public void updatePermission(Long id, RoleUpdatePermissionReq req) {
super.getById(id);
// 保存角色和菜单关联
@@ -148,13 +150,9 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
super.fill(obj);
if (obj instanceof RoleDetailResp detail) {
Long roleId = detail.getId();
if (SysConstants.SUPER_ROLE_CODE.equals(detail.getCode())) {
List<MenuResp> list = menuService.listAll();
List<Long> menuIds = list.stream().map(MenuResp::getId).toList();
detail.setMenuIds(menuIds);
} else {
detail.setMenuIds(roleMenuService.listMenuIdByRoleIds(CollUtil.newArrayList(roleId)));
}
List<MenuResp> list = menuService.listByRoleId(roleId);
List<Long> menuIds = list.stream().map(MenuResp::getId).toList();
detail.setMenuIds(menuIds);
}
}
@@ -194,8 +192,13 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
if (CollUtil.isEmpty(roleIdList)) {
return Collections.emptySet();
}
List<RoleDO> roleList = baseMapper.lambdaQuery().in(RoleDO::getId, roleIdList).list();
return new HashSet<>(BeanUtil.copyToList(roleList, RoleContext.class));
List<RoleDO> roleList = baseMapper.lambdaQuery()
.select(RoleDO::getId, RoleDO::getCode, RoleDO::getDataScope)
.in(RoleDO::getId, roleIdList)
.list();
return roleList.stream()
.map(r -> new RoleContext(r.getId(), r.getCode(), r.getDataScope()))
.collect(Collectors.toSet());
}
@Override

View File

@@ -13,12 +13,12 @@
AND t1.permission IS NOT NULL
</select>
<select id="selectListByRoleCode" resultType="top.continew.admin.system.model.entity.MenuDO">
<select id="selectListByRoleId" resultType="top.continew.admin.system.model.entity.MenuDO">
SELECT t1.*
FROM sys_menu AS t1
LEFT JOIN sys_role_menu AS t2 ON t2.menu_id = t1.id
LEFT JOIN sys_role AS t3 ON t3.id = t2.role_id
WHERE t3.code = #{roleCode}
WHERE t3.id = #{roleId}
AND t1.status = 1
</select>
</mapper>

View File

@@ -131,7 +131,7 @@ public class DemoEnvironmentJob {
roleMenuMapper.lambdaUpdate().notIn(RoleMenuDO::getRoleId, ROLE_FLAG).remove();
return roleMapper.lambdaUpdate().notIn(RoleDO::getId, ROLE_FLAG).remove();
});
this.clean(menuCount, "菜单", CacheConstants.MENU_KEY_PREFIX, () -> menuMapper.lambdaUpdate()
this.clean(menuCount, "菜单", CacheConstants.ROLE_MENU_KEY_PREFIX, () -> menuMapper.lambdaUpdate()
.gt(MenuDO::getId, DELETE_FLAG)
.remove());
this.clean(deptCount, "部门", null, () -> deptMapper.lambdaUpdate().gt(DeptDO::getId, DEPT_FLAG).remove());