update 优化角色逻辑

This commit is contained in:
AprilWind 2025-07-04 10:19:59 +08:00
parent e2200bac71
commit f983ceb86a
4 changed files with 50 additions and 61 deletions

View File

@ -23,6 +23,7 @@ import org.dromara.system.service.ISysUserService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -144,7 +145,7 @@ public class SysRoleController extends BaseController {
@Log(title = "角色管理", businessType = BusinessType.DELETE) @Log(title = "角色管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{roleIds}") @DeleteMapping("/{roleIds}")
public R<Void> remove(@PathVariable Long[] roleIds) { public R<Void> remove(@PathVariable Long[] roleIds) {
return toAjax(roleService.deleteRoleByIds(roleIds)); return toAjax(roleService.deleteRoleByIds(Arrays.asList(roleIds)));
} }
/** /**

View File

@ -1,5 +1,6 @@
package org.dromara.system.mapper; package org.dromara.system.mapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.system.domain.SysUserRole; import org.dromara.system.domain.SysUserRole;
@ -20,4 +21,14 @@ public interface SysUserRoleMapper extends BaseMapperPlus<SysUserRole, SysUserRo
*/ */
List<Long> selectUserIdsByRoleId(Long roleId); List<Long> selectUserIdsByRoleId(Long roleId);
/**
* 根据角色ID统计关联的用户数量
*
* @param roleId 角色ID
* @return 绑定该角色的用户数量
*/
default long countUserByRoleId(Long roleId) {
return selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
}
} }

View File

@ -167,7 +167,7 @@ public interface ISysRoleService {
* @param roleIds 需要删除的角色ID * @param roleIds 需要删除的角色ID
* @return 结果 * @return 结果
*/ */
int deleteRoleByIds(Long[] roleIds); int deleteRoleByIds(List<Long> roleIds);
/** /**
* 取消授权用户角色 * 取消授权用户角色
@ -195,8 +195,18 @@ public interface ISysRoleService {
*/ */
int insertAuthUsers(Long roleId, Long[] userIds); int insertAuthUsers(Long roleId, Long[] userIds);
/**
* 根据角色ID强制下线所有拥有该角色的在线用户
*
* @param roleId 角色ID
*/
void cleanOnlineUserByRole(Long roleId); void cleanOnlineUserByRole(Long roleId);
/**
* 强制下线指定用户ID列表中的所有在线用户
*
* @param userIds 用户ID列表
*/
void cleanOnlineUser(List<Long> userIds); void cleanOnlineUser(List<Long> userIds);
} }

View File

@ -1,6 +1,5 @@
package org.dromara.system.service.impl; package org.dromara.system.service.impl;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
@ -15,7 +14,7 @@ import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.CacheNames; import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.constant.SystemConstants;
import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.constant.TenantConstants;
import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.RoleService; import org.dromara.common.core.service.RoleService;
import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.MapstructUtils;
@ -267,7 +266,7 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService {
*/ */
@Override @Override
public long countUserRoleByRoleId(Long roleId) { public long countUserRoleByRoleId(Long roleId) {
return userRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId)); return userRoleMapper.countUserByRoleId(roleId);
} }
/** /**
@ -412,21 +411,20 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService {
@CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, allEntries = true) @CacheEvict(cacheNames = CacheNames.SYS_ROLE_CUSTOM, allEntries = true)
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public int deleteRoleByIds(Long[] roleIds) { public int deleteRoleByIds(List<Long> roleIds) {
for (Long roleId : roleIds) { List<SysRole> list = baseMapper.selectByIds(roleIds);
SysRole role = baseMapper.selectById(roleId); for (SysRole role : list) {
checkRoleAllowed(BeanUtil.toBean(role, SysRoleBo.class)); checkRoleAllowed(BeanUtil.toBean(role, SysRoleBo.class));
checkRoleDataScope(roleId); checkRoleDataScope(role.getRoleId());
if (countUserRoleByRoleId(roleId) > 0) { if (countUserRoleByRoleId(role.getRoleId()) > 0) {
throw new ServiceException(String.format("%1$s已分配不能删除!", role.getRoleName())); throw new ServiceException(String.format("%1$s已分配不能删除!", role.getRoleName()));
} }
} }
List<Long> ids = Arrays.asList(roleIds);
// 删除角色与菜单关联 // 删除角色与菜单关联
roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, ids)); roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId, roleIds));
// 删除角色与部门关联 // 删除角色与部门关联
roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().in(SysRoleDept::getRoleId, ids)); roleDeptMapper.delete(new LambdaQueryWrapper<SysRoleDept>().in(SysRoleDept::getRoleId, roleIds));
return baseMapper.deleteByIds(ids); return baseMapper.deleteByIds(roleIds);
} }
/** /**
@ -492,61 +490,30 @@ public class SysRoleServiceImpl implements ISysRoleService, RoleService {
return rows; return rows;
} }
/**
* 根据角色ID强制下线所有拥有该角色的在线用户
*
* @param roleId 角色ID
*/
@Override @Override
public void cleanOnlineUserByRole(Long roleId) { public void cleanOnlineUserByRole(Long roleId) {
// 如果角色未绑定用户 直接返回 List<Long> userIds = userRoleMapper.selectUserIdsByRoleId(roleId);
Long num = userRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId)); this.cleanOnlineUser(userIds);
if (num == 0) {
return;
}
List<String> keys = StpUtil.searchTokenValue("", 0, -1, false);
if (CollUtil.isEmpty(keys)) {
return;
}
// 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作
keys.parallelStream().forEach(key -> {
String token = StringUtils.substringAfterLast(key, ":");
// 如果已经过期则跳过
if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) {
return;
}
LoginUser loginUser = LoginHelper.getLoginUser(token);
if (ObjectUtil.isNull(loginUser) || CollUtil.isEmpty(loginUser.getRoles())) {
return;
}
if (loginUser.getRoles().stream().anyMatch(r -> r.getRoleId().equals(roleId))) {
try {
StpUtil.logoutByTokenValue(token);
} catch (NotLoginException ignored) {
}
}
});
} }
/**
* 强制下线指定用户ID列表中的所有在线用户
*
* @param userIds 用户ID列表
*/
@Override @Override
public void cleanOnlineUser(List<Long> userIds) { public void cleanOnlineUser(List<Long> userIds) {
List<String> keys = StpUtil.searchTokenValue("", 0, -1, false); if (CollUtil.isEmpty(userIds)) {
if (CollUtil.isEmpty(keys)) {
return; return;
} }
// 角色关联的在线用户量过大会导致redis阻塞卡顿 谨慎操作 for (Long userId : userIds) {
keys.parallelStream().forEach(key -> { StpUtil.kickout(UserType.SYS_USER.getUserType() + ":" + userId);
String token = StringUtils.substringAfterLast(key, ":"); }
// 如果已经过期则跳过
if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < -1) {
return;
}
LoginUser loginUser = LoginHelper.getLoginUser(token);
if (ObjectUtil.isNull(loginUser)) {
return;
}
if (userIds.contains(loginUser.getUserId())) {
try {
StpUtil.logoutByTokenValue(token);
} catch (NotLoginException ignored) {
}
}
});
} }
/** /**