项目启动将角色权限写入缓存
Sync All Branches to GitHub / sync (push) Successful in 2s

This commit is contained in:
2026-01-23 18:09:58 +08:00
parent 865dfa31f5
commit 155376ca6e
9 changed files with 204 additions and 11 deletions
@@ -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;
}
}
@@ -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();
}
@@ -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();
}
@@ -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);
}
@@ -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>
@@ -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>
@@ -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);
}
}
}
@@ -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缓存结束...");
}
}