# 用户信息增强功能说明 ## 概述 本次更新增强了系统的用户信息获取能力,现在可以从登录上下文中直接获取更多用户信息,无需额外查询数据库。 ## 修改内容 ### 1. LoginUser 类新增常量键 **文件**: `yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/LoginUser.java` 新增以下常量: ```java public static final String INFO_KEY_USERNAME = "username"; // 登录用户名 public static final String INFO_KEY_MOBILE = "mobile"; // 手机号 public static final String INFO_KEY_EMAIL = "email"; // 邮箱 public static final String INFO_KEY_SEX = "sex"; // 性别 public static final String INFO_KEY_AVATAR = "avatar"; // 头像 ``` ### 2. OAuth2TokenServiceImpl 增强用户信息构建 **文件**: `yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImpl.java` 在 `buildUserInfo()` 方法中,现在会从 `AdminUserDO` 读取并存储以下信息: - username(用户名) - mobile(手机号) - email(邮箱) - sex(性别) - avatar(头像) - nickname(昵称,原有) - deptId(部门ID,原有) ### 3. SecurityFrameworkUtils 新增静态方法 **文件**: `yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java` 新增以下静态方法: ```java // 获取登录用户名(账号) public static String getLoginUsername() // 获取手机号 public static String getLoginUserMobile() // 获取邮箱 public static String getLoginUserEmail() // 获取性别 public static Integer getLoginUserSex() // 获取头像 public static String getLoginUserAvatar() ``` 原有方法: ```java // 获取用户ID public static Long getLoginUserId() // 获取昵称 public static String getLoginUserNickname() // 获取部门ID public static Long getLoginUserDeptId() ``` ## 使用示例 ### 在 Service 中使用 ```java import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; @Service public class YourService { public void someMethod() { // 获取当前登录用户的各种信息 Long userId = SecurityFrameworkUtils.getLoginUserId(); String username = SecurityFrameworkUtils.getLoginUsername(); String nickname = SecurityFrameworkUtils.getLoginUserNickname(); String mobile = SecurityFrameworkUtils.getLoginUserMobile(); String email = SecurityFrameworkUtils.getLoginUserEmail(); Integer sex = SecurityFrameworkUtils.getLoginUserSex(); String avatar = SecurityFrameworkUtils.getLoginUserAvatar(); Long deptId = SecurityFrameworkUtils.getLoginUserDeptId(); // 使用这些信息... } } ``` ### 在 Controller 中使用 ```java import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; @RestController @RequestMapping("/api/example") public class ExampleController { @GetMapping("/current-user") public Map getCurrentUser() { Map userInfo = new HashMap<>(); userInfo.put("userId", SecurityFrameworkUtils.getLoginUserId()); userInfo.put("username", SecurityFrameworkUtils.getLoginUsername()); userInfo.put("nickname", SecurityFrameworkUtils.getLoginUserNickname()); userInfo.put("mobile", SecurityFrameworkUtils.getLoginUserMobile()); userInfo.put("email", SecurityFrameworkUtils.getLoginUserEmail()); return userInfo; } } ``` ## 优势 ### 1. 性能提升 - **无需额外数据库查询**:用户信息在登录时已加载到 Token 中 - **减少 API 调用**:不需要调用 `AdminUserApi.getUser()` 获取用户信息 - **降低数据库压力**:减少对 `system_users` 表的查询 ### 2. 代码简化 **之前的写法**: ```java Long userId = SecurityFrameworkUtils.getLoginUserId(); AdminUserRespDTO user = adminUserApi.getUser(userId); String username = user.getUsername(); // 可能为 null String mobile = user.getMobile(); ``` **现在的写法**: ```java String username = SecurityFrameworkUtils.getLoginUsername(); String mobile = SecurityFrameworkUtils.getLoginUserMobile(); ``` ### 3. 一致性保证 - 所有信息来自同一个 Token,保证数据一致性 - 避免并发修改导致的数据不一致问题 ## 应用场景 1. **日志记录**:记录操作用户的详细信息 2. **权限控制**:基于用户属性进行权限判断 3. **业务逻辑**:根据用户信息执行不同的业务逻辑 4. **外部接口调用**:传递用户信息给外部系统(如工单下达接口) 5. **审计追踪**:记录用户的完整信息用于审计 ## 注意事项 1. **返回值可能为 null**:所有 `getXXX()` 方法都可能返回 null,使用前请做判空处理 2. **用户信息更新**:用户信息在登录时加载,如果用户信息被修改,需要重新登录才能获取最新信息 3. **性别字段**:`getLoginUserSex()` 返回 Integer 类型,对应 `SexEnum` 枚举值 4. **线程安全**:这些方法从 `SecurityContextHolder` 获取信息,是线程安全的 ## 实际应用:工单下达接口 在 `WorkOrderServiceImpl` 中的应用示例: ```java private String getCurrentUserName() { // 优先使用登录用户名(username),如果没有则使用昵称(nickname) String username = SecurityFrameworkUtils.getLoginUsername(); if (StrUtil.isNotBlank(username)) { return username; } String nickname = SecurityFrameworkUtils.getLoginUserNickname(); if (StrUtil.isNotBlank(nickname)) { return nickname; } return "system"; } ``` 这样可以优先使用英文的 username,避免中文昵称导致的外部接口调用问题。 ## 兼容性 - ✅ 完全向后兼容 - ✅ 不影响现有代码 - ✅ 可选择性使用新功能 - ✅ 无需修改数据库结构 - ✅ 无需修改配置文件 ## 总结 本次增强为系统提供了更便捷、高效的用户信息获取方式,特别适合需要频繁获取用户信息的场景。建议在新代码中优先使用 `SecurityFrameworkUtils` 的静态方法,而不是通过 API 查询数据库。