🎨 feat: 修改用户缓存使用事件监听

This commit is contained in:
bunny 2025-05-06 16:23:42 +08:00
parent 382f0e4e92
commit 94e0d7f264
24 changed files with 325 additions and 263 deletions

View File

@ -26,6 +26,7 @@ ENTRYPOINT ["java","-jar","/home/server/app.jar"]
#暴露 8000 端口 #暴露 8000 端口
EXPOSE 8000 EXPOSE 8000
EXPOSE 7070
# 生产环境 # 生产环境
# mvn clean package -Pprod -DskipTests # mvn clean package -Pprod -DskipTests

View File

@ -1,13 +1,13 @@
package cn.bunny.services.controller.configuration; package cn.bunny.services.controller.configuration;
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.common.model.vo.result.PageResult;
import cn.bunny.services.domain.common.model.vo.result.Result;
import cn.bunny.services.domain.system.email.dto.EmailTemplateAddDto; import cn.bunny.services.domain.system.email.dto.EmailTemplateAddDto;
import cn.bunny.services.domain.system.email.dto.EmailTemplateDto; import cn.bunny.services.domain.system.email.dto.EmailTemplateDto;
import cn.bunny.services.domain.system.email.dto.EmailTemplateUpdateDto; import cn.bunny.services.domain.system.email.dto.EmailTemplateUpdateDto;
import cn.bunny.services.domain.system.email.entity.EmailTemplate; import cn.bunny.services.domain.system.email.entity.EmailTemplate;
import cn.bunny.services.domain.system.email.vo.EmailTemplateVo; import cn.bunny.services.domain.system.email.vo.EmailTemplateVo;
import cn.bunny.services.domain.common.model.vo.result.PageResult;
import cn.bunny.services.domain.common.model.vo.result.Result;
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.service.configuration.EmailTemplateService; import cn.bunny.services.service.configuration.EmailTemplateService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -71,7 +71,7 @@ public class EmailTemplateController {
} }
@Operation(summary = "全部邮件类型列表", description = "获取全部邮件类型列表", tags = "emailTemplate::query") @Operation(summary = "全部邮件类型列表", description = "获取全部邮件类型列表", tags = "emailTemplate::query")
@GetMapping("public") @GetMapping("private")
public Result<List<Map<String, String>>> getEmailTypeList() { public Result<List<Map<String, String>>> getEmailTypeList() {
List<Map<String, String>> list = emailTemplateService.getEmailTypeList(); List<Map<String, String>> list = emailTemplateService.getEmailTypeList();
return Result.success(list); return Result.success(list);

View File

@ -1,6 +1,8 @@
server: server:
port: 8000 port: 8000
tomcat:
threads:
max: 1000
spring: spring:
profiles: profiles:
active: @profiles.active@ active: @profiles.active@

View File

@ -107,15 +107,4 @@ public class UserAuthorizationCacheService {
return permissionList; return permissionList;
} }
/**
* 清除缓存
* 如有需要清除当前服务缓存
*/
public void deleteRoleAndPermissionCache(String key) {
String permissionCodePrefix = RedisUserConstant.getUserPermissionCodePrefix(key);
String rolesCodePrefix = RedisUserConstant.getUserRolesCodePrefix(key);
redisTemplate.delete(permissionCodePrefix);
redisTemplate.delete(rolesCodePrefix);
}
} }

View File

@ -0,0 +1,33 @@
package cn.bunny.services.core.cache;
import cn.bunny.services.domain.common.constant.RedisUserConstant;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class UserCacheCleaner {
@Resource
private RedisTemplate<String, Object> redisTemplate;
public void cleanUserLoginCache(String username) {
String key = RedisUserConstant.getUserLoginInfoPrefix(username);
redisTemplate.delete(key);
}
public void cleanUserRoleCache(String username) {
String key = RedisUserConstant.getUserRolesCodePrefix(username);
redisTemplate.delete(key);
}
public void cleanUserPermissionCache(String username) {
String key = RedisUserConstant.getUserPermissionCodePrefix(username);
redisTemplate.delete(key);
}
public void cleanAllUserCache(String username) {
cleanUserLoginCache(username);
cleanUserRoleCache(username);
cleanUserPermissionCache(username);
}
}

View File

@ -1,25 +0,0 @@
package cn.bunny.services.core.cache;
import cn.bunny.services.domain.common.constant.RedisUserConstant;
import cn.bunny.services.domain.common.model.vo.LoginVo;
import com.alibaba.fastjson2.JSON;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class UserCacheService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 根据用户名获取缓存中内容
*
* @param username 用户名
* @return LoginVo
*/
public LoginVo getLoginVoByUsername(String username) {
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(username));
return JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
}
}

View File

@ -0,0 +1,16 @@
package cn.bunny.services.core.event.event;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
@Getter
@Setter
public class ClearAllUserCacheEvent extends ApplicationEvent {
private final String key;
public ClearAllUserCacheEvent(Object source, String key) {
super(source);
this.key = key;
}
}

View File

@ -0,0 +1,18 @@
package cn.bunny.services.core.event.event;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
import java.util.List;
@Getter
@Setter
public class UpdateUserinfoByPermissionIdsEvent extends ApplicationEvent {
private final List<Long> permissionIds;
public UpdateUserinfoByPermissionIdsEvent(Object source, List<Long> permissionIds) {
super(source);
this.permissionIds = permissionIds;
}
}

View File

@ -0,0 +1,18 @@
package cn.bunny.services.core.event.event;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
import java.util.List;
@Getter
@Setter
public class UpdateUserinfoByRoleIdsEvent extends ApplicationEvent {
private final List<Long> roleIds;
public UpdateUserinfoByRoleIdsEvent(Object source, List<Long> roleIds) {
super(source);
this.roleIds = roleIds;
}
}

View File

@ -0,0 +1,19 @@
package cn.bunny.services.core.event.event;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
import java.util.List;
@Getter
@Setter
public class UpdateUserinfoByUserIdsEvent extends ApplicationEvent {
private final List<Long> userIds;
public UpdateUserinfoByUserIdsEvent(Object source, List<Long> userIds) {
super(source);
this.userIds = userIds;
}
}

View File

@ -1,4 +1,4 @@
package cn.bunny.services.core.excel; package cn.bunny.services.core.event.listener.excel;
import cn.bunny.services.domain.common.model.dto.excel.I18nExcel; import cn.bunny.services.domain.common.model.dto.excel.I18nExcel;
import cn.bunny.services.domain.system.i18n.entity.I18n; import cn.bunny.services.domain.system.i18n.entity.I18n;

View File

@ -1,4 +1,4 @@
package cn.bunny.services.core.excel; package cn.bunny.services.core.event.listener.excel;
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel; import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
import cn.bunny.services.domain.system.system.entity.Permission; import cn.bunny.services.domain.system.system.entity.Permission;

View File

@ -1,4 +1,4 @@
package cn.bunny.services.core.excel; package cn.bunny.services.core.event.listener.excel;
import cn.bunny.services.domain.common.enums.ResultCodeEnum; import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel; import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;

View File

@ -0,0 +1,34 @@
package cn.bunny.services.core.event.listener.user;
import cn.bunny.services.core.cache.UserCacheCleaner;
import cn.bunny.services.domain.common.constant.RedisUserConstant;
import cn.bunny.services.domain.system.system.entity.AdminUser;
import cn.bunny.services.mapper.system.UserMapper;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.function.Consumer;
@Component("AbstractUserInfoUpdateHandler")
public abstract class AbstractUserInfoUpdateHandler {
@Resource
protected UserMapper userMapper;
@Resource
protected UserCacheCleaner userCacheCleaner;
@Resource
private RedisTemplate<String, Object> redisTemplate;
public void processUserUpdate(List<Long> userIds, Consumer<AdminUser> postProcess) {
if (userIds.isEmpty()) return;
List<AdminUser> adminUsers = userMapper.selectBatchIds(userIds);
adminUsers.stream()
.filter(user -> redisTemplate.hasKey(RedisUserConstant.getUserLoginInfoPrefix(user.getUsername())))
.forEach(postProcess);
}
}

View File

@ -0,0 +1,68 @@
package cn.bunny.services.core.event.listener.user;
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
import cn.bunny.services.core.event.event.ClearAllUserCacheEvent;
import cn.bunny.services.core.event.event.UpdateUserinfoByPermissionIdsEvent;
import cn.bunny.services.core.event.event.UpdateUserinfoByRoleIdsEvent;
import cn.bunny.services.core.event.event.UpdateUserinfoByUserIdsEvent;
import cn.bunny.services.domain.common.constant.RedisUserConstant;
import cn.bunny.services.domain.system.system.entity.RolePermission;
import cn.bunny.services.domain.system.system.entity.UserRole;
import cn.bunny.services.mapper.system.RolePermissionMapper;
import cn.bunny.services.mapper.system.UserRoleMapper;
import jakarta.annotation.Resource;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("UserinfoUpdateListener")
public class UserinfoUpdateListener extends AbstractUserInfoUpdateHandler {
@Resource
private UserLoginVoBuilderCacheService userLoginVoBuilderCacheService;
@Resource
private UserRoleMapper userRoleMapper;
@Resource
private RolePermissionMapper rolePermissionMapper;
/* 根据用户id更新用户信息重新生成LoginVo对象 */
@EventListener
public void handlerUpdateUserinfoByUserIds(UpdateUserinfoByUserIdsEvent event) {
List<Long> userIds = event.getUserIds();
processUserUpdate(userIds, user -> {
userCacheCleaner.cleanAllUserCache(user.getUsername());
userLoginVoBuilderCacheService.buildLoginUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
});
}
/* 根据角色id更新用户信息重新生成LoginVo对象 */
@EventListener
public void handlerUserinfoUpdateByRoleId(UpdateUserinfoByRoleIdsEvent event) {
List<Long> roleIds = event.getRoleIds();
List<UserRole> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
List<Long> userIds = userRoles.stream().map(UserRole::getUserId).toList();
UpdateUserinfoByUserIdsEvent userIdsEvent = new UpdateUserinfoByUserIdsEvent(event.getSource(), userIds);
handlerUpdateUserinfoByUserIds(userIdsEvent);
}
/* 根据角色id更新用户信息重新生成LoginVo对象 */
@EventListener
public void handlerUserinfoUpdateByPermissionId(UpdateUserinfoByPermissionIdsEvent event) {
List<Long> permissionIds = event.getPermissionIds();
List<RolePermission> rolePermissions = rolePermissionMapper.selectRolePermissionListByPermissionIds(permissionIds);
List<Long> roleIds = rolePermissions.stream().map(RolePermission::getRoleId).toList();
UpdateUserinfoByRoleIdsEvent roleIdsEvent = new UpdateUserinfoByRoleIdsEvent(event.getSource(), roleIds);
handlerUserinfoUpdateByRoleId(roleIdsEvent);
}
/* 清除用户登录、角色、权限所有缓存 */
@EventListener
public void handlerDeleteAllUserCache(ClearAllUserCacheEvent event) {
userCacheCleaner.cleanAllUserCache(event.getKey());
}
}

View File

@ -1,160 +0,0 @@
package cn.bunny.services.core.utils;
import cn.bunny.services.core.cache.UserAuthorizationCacheService;
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
import cn.bunny.services.domain.common.constant.RedisUserConstant;
import cn.bunny.services.domain.system.log.entity.UserLoginLog;
import cn.bunny.services.domain.system.system.entity.AdminUser;
import cn.bunny.services.domain.system.system.entity.RolePermission;
import cn.bunny.services.domain.system.system.entity.UserRole;
import cn.bunny.services.mapper.log.UserLoginLogMapper;
import cn.bunny.services.mapper.system.RolePermissionMapper;
import cn.bunny.services.mapper.system.UserMapper;
import cn.bunny.services.mapper.system.UserRoleMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.List;
@Service
public class UserServiceHelper {
@Resource
private UserRoleMapper userRoleMapper;
@Resource
private UserLoginVoBuilderCacheService userLoginVoBuilderCacheService;
@Resource
private UserLoginLogMapper userLoginLogMapper;
@Resource
private RolePermissionMapper rolePermissionMapper;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private UserMapper userMapper;
@Resource
private UserAuthorizationCacheService userAuthorizationCacheService;
/**
* 设置用户登录日志内容
* <p>
* 该方法用于将管理员用户信息复制到用户登录日志对象中同时处理特殊字段映射关系
* <p>
* 实现说明
* 1. 使用BeanUtils.copyProperties()复制属性时会自动将AdminUser.id复制到UserLoginLog.id
* 2. 由于UserLoginLog实际需要的是userId字段而非id字段需要特殊处理
* - 先进行属性复制
* - 然后将UserLoginLog.userId设置为AdminUser.id
* - 最后将UserLoginLog.id显式设为null避免自动生成的id被覆盖
*
* @param user 管理员用户实体对象包含用户基本信息
* @param token 本次登录/退出的认证令牌
* @param type 操作类型LOGIN-登录/LOGOUT-退出
*/
public void setUserLoginLog(AdminUser user, String token, String type) {
UserLoginLog userLoginLog = new UserLoginLog();
BeanUtils.copyProperties(user, userLoginLog);
userLoginLog.setUserId(user.getId());
userLoginLog.setId(null);
userLoginLog.setToken(token);
userLoginLog.setType(type);
// 当前请求request
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = requestAttributes.getRequest();
// 获取User-Agent
String userAgent = request.getHeader("User-Agent");
userLoginLog.setUserAgent(userAgent);
// 获取X-Requested-With
String xRequestedWith = request.getHeader("X-Requested-With");
userLoginLog.setXRequestedWith(xRequestedWith);
}
userLoginLogMapper.insert(userLoginLog);
}
/**
* 批量更新Redis中用户权限信息设计用户和角色就用这个
*
* @param userIds 需要更新的用户ID集合
* 仅处理集合中存在的有效用户
* @see RedisUserConstant Redis键前缀常量
*/
public void updateUserRedisInfo(List<Long> userIds) {
if (userIds.isEmpty()) return;
// 批量查询用户
List<AdminUser> adminUsers = userMapper.selectBatchIds(userIds);
// 并行处理用户更新
adminUsers.stream()
.filter(user -> redisTemplate.hasKey(RedisUserConstant.getUserLoginInfoPrefix(user.getUsername())))
.forEach(user -> {
// 更新时清除缓存中的角色和权限
String username = user.getUsername();
userAuthorizationCacheService.deleteRoleAndPermissionCache(username);
// 更新用户权限信息
userLoginVoBuilderCacheService.buildLoginUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
});
}
/**
* 处理角色更新事件
*
* @param roleIds 角色ID
*/
@Async
public void updateBatchUserRedisInfoByRoleId(List<Long> roleIds) {
// 批量查询关联用户ID
List<UserRole> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
List<Long> userIds = userRoles.stream().map(UserRole::getUserId).toList();
updateUserRedisInfo(userIds);
}
/**
* 处理权限更新事件
*
* @param permissionIds 权限ID
*/
@Async
public void updateBatchUserRedisInfoByPermissionId(List<Long> permissionIds) {
// 批量查询关联用户ID
List<RolePermission> rolePermissions = rolePermissionMapper.selectRolePermissionListByPermissionIds(permissionIds);
List<Long> roleIds = rolePermissions.stream().map(RolePermission::getRoleId).toList();
updateBatchUserRedisInfoByRoleId(roleIds);
}
/**
* 清除用户登录时的缓存
*
* @param username 用户名
*/
public void deleteLoginUserCache(String username) {
String userRolesCodePrefix = RedisUserConstant.getUserRolesCodePrefix(username);
redisTemplate.delete(userRolesCodePrefix);
}
/**
* 清除用户登录时的缓存
*
* @param username 用户名
*/
public void deleteUserCache(String username) {
userAuthorizationCacheService.deleteRoleAndPermissionCache(username);
deleteLoginUserCache(username);
}
}

View File

@ -1,13 +1,15 @@
package cn.bunny.services.security.service; package cn.bunny.services.security.service;
import cn.bunny.services.core.cache.UserCacheService; import cn.bunny.services.domain.common.constant.RedisUserConstant;
import cn.bunny.services.domain.common.enums.ResultCodeEnum; import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.common.model.dto.security.TokenInfo; import cn.bunny.services.domain.common.model.dto.security.TokenInfo;
import cn.bunny.services.domain.common.model.vo.LoginVo; import cn.bunny.services.domain.common.model.vo.LoginVo;
import cn.bunny.services.security.exception.CustomAuthenticationException; import cn.bunny.services.security.exception.CustomAuthenticationException;
import cn.bunny.services.utils.JwtTokenUtil; import cn.bunny.services.utils.JwtTokenUtil;
import com.alibaba.fastjson2.JSON;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
@ -17,7 +19,7 @@ import org.springframework.stereotype.Service;
public class TokenValidationService { public class TokenValidationService {
@Resource @Resource
private UserCacheService userCacheService; private RedisTemplate<String, Object> redisTemplate;
public TokenInfo validateToken(HttpServletRequest request) { public TokenInfo validateToken(HttpServletRequest request) {
// 判断是否有 token // 判断是否有 token
@ -37,7 +39,8 @@ public class TokenValidationService {
Long userId = JwtTokenUtil.getUserId(token); Long userId = JwtTokenUtil.getUserId(token);
// 查找 Redis // 查找 Redis
LoginVo loginVo = userCacheService.getLoginVoByUsername(username); Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(username));
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
return TokenInfo.builder().userId(userId).username(username).token(token).loginVo(loginVo).build(); return TokenInfo.builder().userId(userId).username(username).token(token).loginVo(loginVo).build();
} }

View File

@ -1,6 +1,6 @@
package cn.bunny.services.service.configuration.impl; package cn.bunny.services.service.configuration.impl;
import cn.bunny.services.core.excel.I18nExcelListener; import cn.bunny.services.core.event.listener.excel.I18nExcelListener;
import cn.bunny.services.core.strategy.export.ExcelExportStrategy; import cn.bunny.services.core.strategy.export.ExcelExportStrategy;
import cn.bunny.services.core.strategy.export.JsonExportStrategy; import cn.bunny.services.core.strategy.export.JsonExportStrategy;
import cn.bunny.services.domain.common.constant.FileType; import cn.bunny.services.domain.common.constant.FileType;

View File

@ -1,10 +1,10 @@
package cn.bunny.services.service.system.impl; package cn.bunny.services.service.system.impl;
import cn.bunny.services.core.excel.PermissionExcelListener; import cn.bunny.services.core.event.event.UpdateUserinfoByPermissionIdsEvent;
import cn.bunny.services.core.event.listener.excel.PermissionExcelListener;
import cn.bunny.services.core.strategy.export.ExcelExportStrategy; import cn.bunny.services.core.strategy.export.ExcelExportStrategy;
import cn.bunny.services.core.strategy.export.JsonExportStrategy; import cn.bunny.services.core.strategy.export.JsonExportStrategy;
import cn.bunny.services.core.template.PermissionTreeProcessor; import cn.bunny.services.core.template.PermissionTreeProcessor;
import cn.bunny.services.core.utils.UserServiceHelper;
import cn.bunny.services.domain.common.constant.FileType; import cn.bunny.services.domain.common.constant.FileType;
import cn.bunny.services.domain.common.enums.ResultCodeEnum; import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel; import cn.bunny.services.domain.common.model.dto.excel.PermissionExcel;
@ -32,6 +32,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching; import org.springframework.cache.annotation.Caching;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -63,7 +64,7 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
private static final String CACHE_NAMES = "permission"; private static final String CACHE_NAMES = "permission";
@Resource @Resource
private UserServiceHelper userServiceHelper; private ApplicationEventPublisher applicationEventPublisher;
/** /**
* 将树形结构权限数据扁平化为列表 * 将树形结构权限数据扁平化为列表
@ -156,7 +157,8 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
BeanUtils.copyProperties(dto, permission); BeanUtils.copyProperties(dto, permission);
updateById(permission); updateById(permission);
userServiceHelper.updateBatchUserRedisInfoByPermissionId(List.of(dto.getId())); List<Long> ids = List.of(dto.getId());
applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
} }
/** /**
@ -174,7 +176,7 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY); if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
// 删除缓存中所有这个权限关联的用户角色和权限信息 // 删除缓存中所有这个权限关联的用户角色和权限信息
userServiceHelper.updateBatchUserRedisInfoByPermissionId(ids); applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
// 删除权限 // 删除权限
removeByIds(ids); removeByIds(ids);
@ -190,7 +192,8 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
@CacheEvict(cacheNames = CACHE_NAMES, key = "'permissionList'", beforeInvocation = true), @CacheEvict(cacheNames = CACHE_NAMES, key = "'permissionList'", beforeInvocation = true),
}) })
public void updatePermissionListByParentId(PermissionUpdateBatchByParentIdDto dto) { public void updatePermissionListByParentId(PermissionUpdateBatchByParentIdDto dto) {
List<Permission> permissionList = dto.getIds().stream().map(id -> { List<Long> ids = dto.getIds();
List<Permission> permissionList = ids.stream().map(id -> {
Permission permission = new Permission(); Permission permission = new Permission();
permission.setId(id); permission.setId(id);
permission.setParentId(dto.getParentId()); permission.setParentId(dto.getParentId());
@ -198,7 +201,7 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
}).toList(); }).toList();
// 删除缓存中所有这个权限关联的用户角色和权限信息 // 删除缓存中所有这个权限关联的用户角色和权限信息
userServiceHelper.updateBatchUserRedisInfoByPermissionId(dto.getIds()); applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
updateBatchById(permissionList); updateBatchById(permissionList);
} }
@ -312,6 +315,6 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
// 删除缓存中所有这个权限关联的用户角色和权限信息 // 删除缓存中所有这个权限关联的用户角色和权限信息
List<Long> ids = list.stream().map(PermissionUpdateDto::getId).toList(); List<Long> ids = list.stream().map(PermissionUpdateDto::getId).toList();
userServiceHelper.updateBatchUserRedisInfoByPermissionId(ids); applicationEventPublisher.publishEvent(new UpdateUserinfoByPermissionIdsEvent(this, ids));
} }
} }

View File

@ -1,6 +1,6 @@
package cn.bunny.services.service.system.impl; package cn.bunny.services.service.system.impl;
import cn.bunny.services.core.utils.UserServiceHelper; import cn.bunny.services.core.event.event.UpdateUserinfoByRoleIdsEvent;
import cn.bunny.services.domain.system.system.dto.AssignPowersToRoleDto; import cn.bunny.services.domain.system.system.dto.AssignPowersToRoleDto;
import cn.bunny.services.domain.system.system.entity.AdminUser; import cn.bunny.services.domain.system.system.entity.AdminUser;
import cn.bunny.services.domain.system.system.entity.RolePermission; import cn.bunny.services.domain.system.system.entity.RolePermission;
@ -12,6 +12,7 @@ import cn.bunny.services.service.system.RolePermissionService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -36,7 +37,7 @@ public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper,
private UserRoleMapper userRoleMapper; private UserRoleMapper userRoleMapper;
@Resource @Resource
private UserServiceHelper userServiceHelper; private ApplicationEventPublisher applicationEventPublisher;
/** /**
* * 根据角色id获取权限内容 * * 根据角色id获取权限内容
@ -63,7 +64,8 @@ public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper,
Long roleId = dto.getRoleId(); Long roleId = dto.getRoleId();
// 删除这个角色下所有权限 // 删除这个角色下所有权限
baseMapper.deleteBatchRoleIds(List.of(roleId)); List<Long> ids = List.of(roleId);
baseMapper.deleteBatchRoleIds(ids);
// 保存分配数据 // 保存分配数据
List<RolePermission> rolePermissionList = powerIds.stream().map(powerId -> { List<RolePermission> rolePermissionList = powerIds.stream().map(powerId -> {
@ -85,6 +87,6 @@ public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper,
if (adminUsers.isEmpty()) return; if (adminUsers.isEmpty()) return;
// 更新角色绑定的用户 // 更新角色绑定的用户
userServiceHelper.updateBatchUserRedisInfoByRoleId(List.of(roleId)); applicationEventPublisher.publishEvent(new UpdateUserinfoByRoleIdsEvent(this, ids));
} }
} }

View File

@ -1,7 +1,7 @@
package cn.bunny.services.service.system.impl; package cn.bunny.services.service.system.impl;
import cn.bunny.services.core.excel.RoleExcelListener; import cn.bunny.services.core.event.event.UpdateUserinfoByRoleIdsEvent;
import cn.bunny.services.core.utils.UserServiceHelper; import cn.bunny.services.core.event.listener.excel.RoleExcelListener;
import cn.bunny.services.domain.common.enums.ResultCodeEnum; import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.common.model.dto.excel.RoleExcel; import cn.bunny.services.domain.common.model.dto.excel.RoleExcel;
import cn.bunny.services.domain.common.model.vo.result.PageResult; import cn.bunny.services.domain.common.model.vo.result.PageResult;
@ -12,9 +12,6 @@ import cn.bunny.services.domain.system.system.entity.Role;
import cn.bunny.services.domain.system.system.vo.RoleVo; import cn.bunny.services.domain.system.system.vo.RoleVo;
import cn.bunny.services.exception.AuthCustomerException; import cn.bunny.services.exception.AuthCustomerException;
import cn.bunny.services.mapper.system.RoleMapper; import cn.bunny.services.mapper.system.RoleMapper;
import cn.bunny.services.mapper.system.RolePermissionMapper;
import cn.bunny.services.mapper.system.RouterRoleMapper;
import cn.bunny.services.mapper.system.UserRoleMapper;
import cn.bunny.services.service.system.RoleService; import cn.bunny.services.service.system.RoleService;
import cn.bunny.services.utils.FileUtil; import cn.bunny.services.utils.FileUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
@ -28,6 +25,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching; import org.springframework.cache.annotation.Caching;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -59,16 +57,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
private static final String CACHE_NAMES = "role"; private static final String CACHE_NAMES = "role";
@Resource @Resource
private UserRoleMapper userRoleMapper; private ApplicationEventPublisher applicationEventPublisher;
@Resource
private RolePermissionMapper rolePermissionMapper;
@Resource
private RouterRoleMapper routerRoleMapper;
@Resource
private UserServiceHelper userServiceHelper;
/** /**
* 角色 服务实现类 * 角色 服务实现类
@ -231,7 +220,8 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
updateById(role); updateById(role);
// 发布角色更新事件 // 发布角色更新事件
userServiceHelper.updateBatchUserRedisInfoByRoleId(List.of(roleId)); List<Long> ids = List.of(roleId);
applicationEventPublisher.publishEvent(new UpdateUserinfoByRoleIdsEvent(this, ids));
} }
/** /**
@ -249,7 +239,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY); if (ids.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.REQUEST_IS_EMPTY);
// 重新构建角色和用户缓存 // 重新构建角色和用户缓存
userServiceHelper.updateBatchUserRedisInfoByRoleId(ids); applicationEventPublisher.publishEvent(new UpdateUserinfoByRoleIdsEvent(this, ids));
// 删除角色 // 删除角色
removeByIds(ids); removeByIds(ids);

View File

@ -3,12 +3,12 @@ package cn.bunny.services.service.system.impl;
import cn.bunny.services.context.BaseContext; import cn.bunny.services.context.BaseContext;
import cn.bunny.services.core.cache.EmailCacheService; import cn.bunny.services.core.cache.EmailCacheService;
import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService; import cn.bunny.services.core.cache.UserLoginVoBuilderCacheService;
import cn.bunny.services.core.event.event.ClearAllUserCacheEvent;
import cn.bunny.services.core.strategy.login.DefaultLoginStrategy; import cn.bunny.services.core.strategy.login.DefaultLoginStrategy;
import cn.bunny.services.core.strategy.login.EmailLoginStrategy; import cn.bunny.services.core.strategy.login.EmailLoginStrategy;
import cn.bunny.services.core.strategy.login.LoginContext; import cn.bunny.services.core.strategy.login.LoginContext;
import cn.bunny.services.core.strategy.login.LoginStrategy; import cn.bunny.services.core.strategy.login.LoginStrategy;
import cn.bunny.services.core.template.email.ConcreteSenderEmailTemplate; import cn.bunny.services.core.template.email.ConcreteSenderEmailTemplate;
import cn.bunny.services.core.utils.UserServiceHelper;
import cn.bunny.services.domain.common.constant.RedisUserConstant; import cn.bunny.services.domain.common.constant.RedisUserConstant;
import cn.bunny.services.domain.common.constant.UserConstant; import cn.bunny.services.domain.common.constant.UserConstant;
import cn.bunny.services.domain.common.enums.EmailTemplateEnums; import cn.bunny.services.domain.common.enums.EmailTemplateEnums;
@ -16,6 +16,7 @@ import cn.bunny.services.domain.common.enums.LoginEnums;
import cn.bunny.services.domain.common.enums.ResultCodeEnum; import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.common.model.vo.LoginVo; import cn.bunny.services.domain.common.model.vo.LoginVo;
import cn.bunny.services.domain.system.email.entity.EmailTemplate; import cn.bunny.services.domain.system.email.entity.EmailTemplate;
import cn.bunny.services.domain.system.log.entity.UserLoginLog;
import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateByLocalUserDto; import cn.bunny.services.domain.system.system.dto.user.AdminUserUpdateByLocalUserDto;
import cn.bunny.services.domain.system.system.dto.user.LoginDto; import cn.bunny.services.domain.system.system.dto.user.LoginDto;
import cn.bunny.services.domain.system.system.dto.user.RefreshTokenDto; import cn.bunny.services.domain.system.system.dto.user.RefreshTokenDto;
@ -23,6 +24,7 @@ import cn.bunny.services.domain.system.system.entity.AdminUser;
import cn.bunny.services.domain.system.system.vo.user.RefreshTokenVo; import cn.bunny.services.domain.system.system.vo.user.RefreshTokenVo;
import cn.bunny.services.exception.AuthCustomerException; import cn.bunny.services.exception.AuthCustomerException;
import cn.bunny.services.mapper.configuration.EmailTemplateMapper; import cn.bunny.services.mapper.configuration.EmailTemplateMapper;
import cn.bunny.services.mapper.log.UserLoginLogMapper;
import cn.bunny.services.mapper.system.UserMapper; import cn.bunny.services.mapper.system.UserMapper;
import cn.bunny.services.minio.MinioHelper; import cn.bunny.services.minio.MinioHelper;
import cn.bunny.services.service.system.UserLoginService; import cn.bunny.services.service.system.UserLoginService;
@ -34,20 +36,21 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.HashMap; import java.util.HashMap;
@Service @Service
public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> implements UserLoginService { public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> implements UserLoginService {
@Resource
private UserServiceHelper userServiceHelper;
@Resource @Resource
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
@ -57,6 +60,9 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
@Resource @Resource
private EmailTemplateMapper emailTemplateMapper; private EmailTemplateMapper emailTemplateMapper;
@Resource
private UserLoginLogMapper userLoginLogMapper;
@Resource @Resource
private ConcreteSenderEmailTemplate concreteSenderEmailTemplate; private ConcreteSenderEmailTemplate concreteSenderEmailTemplate;
@ -70,7 +76,7 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
private EmailCacheService emailCacheService; private EmailCacheService emailCacheService;
@Resource @Resource
private UserServiceHelper serviceHelper; private ApplicationEventPublisher applicationEventPublisher;
/** /**
* 前台用户登录接口 * 前台用户登录接口
@ -131,7 +137,7 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
LoginVo loginVo = userLoginVoBuilderCacheService.buildLoginUserVo(user, readMeDay); LoginVo loginVo = userLoginVoBuilderCacheService.buildLoginUserVo(user, readMeDay);
// 将用户登录保存在用户登录日志表中 // 将用户登录保存在用户登录日志表中
userServiceHelper.setUserLoginLog(user, loginVo.getToken(), UserConstant.LOGIN); setUserLoginLog(user, loginVo.getToken(), UserConstant.LOGIN);
return loginVo; return loginVo;
} }
@ -225,12 +231,11 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId)); AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId));
adminUser.setIpAddress(ipAddr); adminUser.setIpAddress(ipAddr);
adminUser.setIpRegion(ipRegion); adminUser.setIpRegion(ipRegion);
userServiceHelper.setUserLoginLog(adminUser, token, UserConstant.LOGOUT); setUserLoginLog(adminUser, token, UserConstant.LOGOUT);
// 删除Redis中用户信息 // 删除Redis中用户信息
String username = adminUser.getUsername(); String username = adminUser.getUsername();
applicationEventPublisher.publishEvent(new ClearAllUserCacheEvent(this, username));
serviceHelper.deleteUserCache(username);
} }
@ -289,6 +294,48 @@ public class UserLoginServiceImpl extends ServiceImpl<UserMapper, AdminUser> imp
updateById(adminUser); updateById(adminUser);
// 删除Redis中登录用户信息角色权限信息 // 删除Redis中登录用户信息角色权限信息
serviceHelper.deleteUserCache(adminUser.getUsername()); String username = adminUser.getUsername();
applicationEventPublisher.publishEvent(new ClearAllUserCacheEvent(this, username));
}
/**
* 设置用户登录日志内容
* <p>
* 该方法用于将管理员用户信息复制到用户登录日志对象中同时处理特殊字段映射关系
* <p>
* 实现说明
* 1. 使用BeanUtils.copyProperties()复制属性时会自动将AdminUser.id复制到UserLoginLog.id
* 2. 由于UserLoginLog实际需要的是userId字段而非id字段需要特殊处理
* - 先进行属性复制
* - 然后将UserLoginLog.userId设置为AdminUser.id
* - 最后将UserLoginLog.id显式设为null避免自动生成的id被覆盖
*
* @param user 管理员用户实体对象包含用户基本信息
* @param token 本次登录/退出的认证令牌
* @param type 操作类型LOGIN-登录/LOGOUT-退出
*/
public void setUserLoginLog(AdminUser user, String token, String type) {
UserLoginLog userLoginLog = new UserLoginLog();
BeanUtils.copyProperties(user, userLoginLog);
userLoginLog.setUserId(user.getId());
userLoginLog.setId(null);
userLoginLog.setToken(token);
userLoginLog.setType(type);
// 当前请求request
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
HttpServletRequest request = requestAttributes.getRequest();
// 获取User-Agent
String userAgent = request.getHeader("User-Agent");
userLoginLog.setUserAgent(userAgent);
// 获取X-Requested-With
String xRequestedWith = request.getHeader("X-Requested-With");
userLoginLog.setXRequestedWith(xRequestedWith);
}
userLoginLogMapper.insert(userLoginLog);
} }
} }

View File

@ -1,6 +1,6 @@
package cn.bunny.services.service.system.impl; package cn.bunny.services.service.system.impl;
import cn.bunny.services.core.utils.UserServiceHelper; import cn.bunny.services.core.event.event.UpdateUserinfoByUserIdsEvent;
import cn.bunny.services.domain.common.enums.ResultCodeEnum; import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.system.system.dto.user.AssignRolesToUsersDto; import cn.bunny.services.domain.system.system.dto.user.AssignRolesToUsersDto;
import cn.bunny.services.domain.system.system.entity.AdminUser; import cn.bunny.services.domain.system.system.entity.AdminUser;
@ -12,6 +12,7 @@ import cn.bunny.services.service.system.UserRoleService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -36,7 +37,7 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
private UserMapper userMapper; private UserMapper userMapper;
@Resource @Resource
private UserServiceHelper serviceHelper; private ApplicationEventPublisher applicationEventPublisher;
/** /**
* * 根据用户id获取角色列表 * * 根据用户id获取角色列表
@ -69,7 +70,8 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
} }
// 删除这个用户下所有已经分配好的角色内容 // 删除这个用户下所有已经分配好的角色内容
baseMapper.deleteBatchIdsByUserIds(List.of(userId)); List<Long> ids = List.of(userId);
baseMapper.deleteBatchIdsByUserIds(ids);
// 保存分配好的角色信息 // 保存分配好的角色信息
List<UserRole> roleList = roleIds.stream().map(roleId -> { List<UserRole> roleList = roleIds.stream().map(roleId -> {
@ -81,6 +83,6 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
saveBatch(roleList); saveBatch(roleList);
// 重新设置Redis中的用户存储信息vo对象 // 重新设置Redis中的用户存储信息vo对象
serviceHelper.updateUserRedisInfo(List.of(userId)); applicationEventPublisher.publishEvent(new UpdateUserinfoByUserIdsEvent(this, ids));
} }
} }

View File

@ -1,9 +1,10 @@
package cn.bunny.services.service.system.impl; package cn.bunny.services.service.system.impl;
import cn.bunny.services.core.cache.RedisService; import cn.bunny.services.core.cache.RedisService;
import cn.bunny.services.core.cache.UserCacheService; import cn.bunny.services.core.event.event.ClearAllUserCacheEvent;
import cn.bunny.services.core.utils.UserServiceHelper; import cn.bunny.services.core.event.event.UpdateUserinfoByUserIdsEvent;
import cn.bunny.services.domain.common.constant.MinioConstant; import cn.bunny.services.domain.common.constant.MinioConstant;
import cn.bunny.services.domain.common.constant.RedisUserConstant;
import cn.bunny.services.domain.common.constant.UserConstant; import cn.bunny.services.domain.common.constant.UserConstant;
import cn.bunny.services.domain.common.enums.ResultCodeEnum; import cn.bunny.services.domain.common.enums.ResultCodeEnum;
import cn.bunny.services.domain.common.model.vo.LoginVo; import cn.bunny.services.domain.common.model.vo.LoginVo;
@ -29,6 +30,7 @@ import cn.bunny.services.mapper.system.UserRoleMapper;
import cn.bunny.services.minio.MinioHelper; import cn.bunny.services.minio.MinioHelper;
import cn.bunny.services.service.system.FilesService; import cn.bunny.services.service.system.FilesService;
import cn.bunny.services.service.system.UserService; import cn.bunny.services.service.system.UserService;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -37,6 +39,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -81,10 +85,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
private RedisService redisService; private RedisService redisService;
@Resource @Resource
private UserCacheService userCacheService; private RedisTemplate<String, Object> redisTemplate;
@Resource @Resource
private UserServiceHelper userServiceHelper; private ApplicationEventPublisher applicationEventPublisher;
/** /**
* 获取用户信息 * 获取用户信息
@ -144,7 +148,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
// 删除Redis中用户信息 // 删除Redis中用户信息
String username = adminUser.getUsername(); String username = adminUser.getUsername();
userServiceHelper.deleteUserCache(username); applicationEventPublisher.publishEvent(new ClearAllUserCacheEvent(this, username));
} }
/** /**
@ -189,7 +193,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
List<String> keys = redisService.scannerRedisKeyByPage(pageNum, pageSize); List<String> keys = redisService.scannerRedisKeyByPage(pageNum, pageSize);
List<UserVo> list = keys.stream().map(key -> { List<UserVo> list = keys.stream().map(key -> {
LoginVo loginVo = userCacheService.getLoginVoByUsername(key); Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getUserLoginInfoPrefix(key));
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
UserVo userVo = new UserVo(); UserVo userVo = new UserVo();
BeanUtils.copyProperties(loginVo, userVo); BeanUtils.copyProperties(loginVo, userVo);
@ -305,7 +310,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
updateById(adminUser); updateById(adminUser);
// 同步到 Redis // 同步到 Redis
userServiceHelper.updateUserRedisInfo(List.of(adminUser.getId())); List<Long> ids = List.of(adminUser.getId());
applicationEventPublisher.publishEvent(new UpdateUserinfoByUserIdsEvent(this, ids));
} }
/** /**
@ -324,11 +330,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
if (!roleList.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.ADMIN_ROLE_CAN_NOT_DELETED); if (!roleList.isEmpty()) throw new AuthCustomerException(ResultCodeEnum.ADMIN_ROLE_CAN_NOT_DELETED);
// 清除Redis中数据 // 清除Redis中数据
List<AdminUser> adminUserList = list(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, ids)); applicationEventPublisher.publishEvent(new UpdateUserinfoByUserIdsEvent(this, ids));
adminUserList.parallelStream().forEach(adminUser -> {
String username = adminUser.getUsername();
userServiceHelper.deleteLoginUserCache(username);
});
// 删除部门相关 // 删除部门相关
userDeptMapper.deleteBatchIdsByUserIds(ids); userDeptMapper.deleteBatchIdsByUserIds(ids);