This commit is contained in:
+17
-2
@@ -26,9 +26,14 @@ public class RedisKeyConstants {
|
||||
private static final String USER_ROLES_KEY_PREFIX = "user:roles:";
|
||||
|
||||
/**
|
||||
* 小哈书全局 ID 生成器 KEY
|
||||
* 小壹书全局 ID 生成器 KEY
|
||||
*/
|
||||
public static final String XIAOYI_ID_GENERATOR_KEY = "xiaoyishu_id_generator";
|
||||
public static final String XIAOYI_ID_GENERATOR_KEY = "xiaoyishu.id.generator";
|
||||
|
||||
/**
|
||||
* 角色权限数据 KEY 前缀
|
||||
*/
|
||||
public static final String ROLE_PERMISSIONS_KEY_PREFIX = "role:permissions:";
|
||||
|
||||
/**
|
||||
* 构建验证码 KEY
|
||||
@@ -50,4 +55,14 @@ public class RedisKeyConstants {
|
||||
return USER_ROLES_KEY_PREFIX + phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建角色权限数据 KEY
|
||||
*
|
||||
* @param roleId 角色 ID
|
||||
* @return 角色权限数据 KEY
|
||||
*/
|
||||
public static String buildRolePermissionsKey(Long roleId) {
|
||||
return ROLE_PERMISSIONS_KEY_PREFIX + roleId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-1
@@ -1,7 +1,9 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.PermissionEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.PermissionEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
@@ -12,5 +14,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
*/
|
||||
public interface PermissionMapper extends BaseMapper<PermissionEntity> {
|
||||
|
||||
/**
|
||||
* 查询所有已启用的权限列表
|
||||
*
|
||||
* @return 已启用的权限列表
|
||||
*/
|
||||
List<PermissionEntity> selectAppEnabledList();
|
||||
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -1,7 +1,9 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.RoleEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.RoleEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
@@ -12,5 +14,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
*/
|
||||
public interface RoleMapper extends BaseMapper<RoleEntity> {
|
||||
|
||||
/**
|
||||
* 查询所有启用的角色列表
|
||||
*
|
||||
* @return 角色列表
|
||||
*/
|
||||
List<RoleEntity> selectEnabledRoleList();
|
||||
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -1,8 +1,11 @@
|
||||
package top.crushtj.xiaoyishu.auth.domain.mappers;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.RolePermissionRelEntity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
@@ -12,5 +15,13 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
*/
|
||||
public interface RolePermissionRelMapper extends BaseMapper<RolePermissionRelEntity> {
|
||||
|
||||
/**
|
||||
* 根据角色ID查询权限
|
||||
*
|
||||
* @param roleIds 角色ID列表
|
||||
* @return 权限列表
|
||||
*/
|
||||
List<RolePermissionRelEntity> selectByRoleIds(@Param("roleIds") List<Long> roleIds);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -16,5 +16,12 @@
|
||||
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="isDeleted" column="is_deleted" jdbcType="BOOLEAN"/>
|
||||
</resultMap>
|
||||
<select id="selectAppEnabledList" resultType="top.crushtj.xiaoyishu.auth.domain.entity.PermissionEntity">
|
||||
SELECT id, name, permission_key
|
||||
FROM t_permission p
|
||||
WHERE p.status = 1
|
||||
AND p.is_deleted = 0
|
||||
AND type = 3
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -14,4 +14,10 @@
|
||||
<result property="isDeleted" column="is_deleted" jdbcType="BOOLEAN"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectEnabledRoleList" resultType="top.crushtj.xiaoyishu.auth.domain.entity.RoleEntity">
|
||||
SELECT id, role_name, role_key
|
||||
FROM t_role
|
||||
WHERE status = 1
|
||||
AND is_deleted = 0
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
+11
@@ -10,5 +10,16 @@
|
||||
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="isDeleted" column="is_deleted" jdbcType="BOOLEAN"/>
|
||||
</resultMap>
|
||||
<select id="selectByRoleIds" resultType="top.crushtj.xiaoyishu.auth.domain.entity.RolePermissionRelEntity">
|
||||
SELECT role_id, permission_id FROM t_role_permission_rel
|
||||
<where>
|
||||
<if test="roleIds!=null and !roleIds.empty">
|
||||
AND role_id IN
|
||||
<foreach collection="roleIds" item="roleId" open="(" separator="," close=")">
|
||||
#{roleId}
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package top.crushtj.xiaoyishu.auth.runner;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import top.crushtj.framework.common.utils.JsonUtils;
|
||||
import top.crushtj.xiaoyishu.auth.constant.RedisKeyConstants;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.PermissionEntity;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.RoleEntity;
|
||||
import top.crushtj.xiaoyishu.auth.domain.entity.RolePermissionRelEntity;
|
||||
import top.crushtj.xiaoyishu.auth.domain.mappers.PermissionMapper;
|
||||
import top.crushtj.xiaoyishu.auth.domain.mappers.RoleMapper;
|
||||
import top.crushtj.xiaoyishu.auth.domain.mappers.RolePermissionRelMapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ayi
|
||||
* @version V1.0
|
||||
* @title PushRolePermissions2RedisRunner
|
||||
* @date 2026/01/23 16:51
|
||||
* @description 推送角色权限到Redis
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class PushRolePermissions2RedisRunner implements ApplicationRunner {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Resource
|
||||
private RoleMapper roleMapper;
|
||||
|
||||
@Resource
|
||||
private RolePermissionRelMapper rolePermissionRelMapper;
|
||||
|
||||
@Resource
|
||||
private PermissionMapper permissionMapper;
|
||||
|
||||
public static final String PUSH_PERMISSION_FLAG = "push.permission.flag";
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
log.info("==> 开始同步角色权限数据到 Redis 中...");
|
||||
|
||||
try {
|
||||
// 是否能够同步数据: 原子操作,只有在键 PUSH_PERMISSION_FLAG 不存在时,才会设置该键的值为 "1",并设置过期时间为 1 天
|
||||
boolean canPushed = Boolean.TRUE.equals(redisTemplate.opsForValue()
|
||||
.setIfAbsent(PUSH_PERMISSION_FLAG, "1", 1, TimeUnit.DAYS));
|
||||
// 如果无法同步权限数据
|
||||
if (!canPushed) {
|
||||
log.warn("==> 角色权限数据已经同步至 Redis 中,不再同步...");
|
||||
return;
|
||||
}
|
||||
// 查询所有已启用角色
|
||||
List<RoleEntity> roleList = roleMapper.selectEnabledRoleList();
|
||||
if (CollUtil.isNotEmpty(roleList)) {
|
||||
// 获取角色ID集合
|
||||
List<Long> roleIds = roleList.stream()
|
||||
.map(RoleEntity::getId)
|
||||
.toList();
|
||||
|
||||
//查询角色对应的权限
|
||||
List<RolePermissionRelEntity> rolePermissionList = rolePermissionRelMapper.selectByRoleIds(roleIds);
|
||||
|
||||
// 按角色 ID 分组, 每个角色 ID 对应多个权限 ID
|
||||
Map<Long, List<Long>> roleIdPermissionIdsMap = rolePermissionList.stream()
|
||||
.collect(Collectors.groupingBy(RolePermissionRelEntity::getRoleId,
|
||||
Collectors.mapping(RolePermissionRelEntity::getPermissionId, Collectors.toList())));
|
||||
|
||||
// 查询所有启用的权限
|
||||
List<PermissionEntity> permissionList = permissionMapper.selectAppEnabledList();
|
||||
|
||||
// 构建权限 ID 和权限 DO 对象的映射关系
|
||||
Map<Long, PermissionEntity> permissionIdEntityMap = permissionList.stream()
|
||||
.collect(Collectors.toMap(PermissionEntity::getId, permissionEntity -> permissionEntity));
|
||||
|
||||
// 构建角色 ID 和权限 DO 列表的映射关系
|
||||
Map<Long, List<PermissionEntity>> roleIdPermissionMap = new HashMap<>();
|
||||
roleList.forEach(role -> {
|
||||
Long roleId = role.getId();
|
||||
//获取角色对应的权限id列表
|
||||
List<Long> permissionIds = roleIdPermissionIdsMap.get(roleId);
|
||||
if (CollUtil.isNotEmpty(permissionIds)) {
|
||||
List<PermissionEntity> perDOS = Lists.newArrayList();
|
||||
permissionIds.forEach(permissionId -> {
|
||||
// 根据权限 ID 获取具体的权限 DO 对象
|
||||
PermissionEntity permissionDO = permissionIdEntityMap.get(permissionId);
|
||||
if (Objects.nonNull(permissionDO)) {
|
||||
perDOS.add(permissionDO);
|
||||
}
|
||||
});
|
||||
roleIdPermissionMap.put(roleId, perDOS);
|
||||
}
|
||||
});
|
||||
|
||||
// 将角色 ID 和权限 DO 列表的映射关系写入 Redis
|
||||
roleIdPermissionMap.forEach((roleId, permission) -> {
|
||||
String key = RedisKeyConstants.buildRolePermissionsKey(roleId);
|
||||
redisTemplate.opsForValue()
|
||||
.set(key, JsonUtils.toJsonString(permission));
|
||||
});
|
||||
}
|
||||
log.info("==> 角色权限数据同步到 Redis 完成...");
|
||||
} catch (Exception e) {
|
||||
log.error("==> 角色权限数据同步到 Redis 失败...", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+7
-5
@@ -1,4 +1,4 @@
|
||||
package top.crushtj.xiaoyishu.auth.cache;
|
||||
package top.crushtj.xiaoyishu.auth.runner.cache;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
@@ -34,16 +34,18 @@ public class CacheLoader {
|
||||
*/
|
||||
@PostConstruct
|
||||
public void loadUserCache() {
|
||||
log.info("加载用户自增ID缓存开始...");
|
||||
log.info("==> 加载用户自增ID缓存开始...");
|
||||
LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.orderByDesc(UserEntity::getXiaoyishuId);
|
||||
queryWrapper.last("limit 1");
|
||||
UserEntity user = userMapper.selectOne(queryWrapper);
|
||||
if (user != null) {
|
||||
redisTemplate.opsForValue().set(XIAOYI_ID_GENERATOR_KEY, Long.valueOf(user.getXiaoyishuId()));
|
||||
redisTemplate.opsForValue()
|
||||
.set(XIAOYI_ID_GENERATOR_KEY, Long.valueOf(user.getXiaoyishuId()));
|
||||
} else {
|
||||
redisTemplate.opsForValue().set(XIAOYI_ID_GENERATOR_KEY, XIAOYI_ID_INITIAL_VALUE);
|
||||
redisTemplate.opsForValue()
|
||||
.set(XIAOYI_ID_GENERATOR_KEY, XIAOYI_ID_INITIAL_VALUE);
|
||||
}
|
||||
log.info("加载用户自增ID缓存结束...");
|
||||
log.info("==> 加载用户自增ID缓存结束...");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user