商户登录util.md 19 KB

LoginUserUtil 工具类使用文档

概述

LoginUserUtil 是一个用于在web端商户平台(alien-store-platform)中获取当前登录用户信息的工具类。它封装了从JWT Token中提取用户信息以及从数据库查询完整用户信息的常用方法。


核心特性

  • 静态方法: 所有方法都是静态方法,可直接调用,无需实例化
  • 自动注入: 使用@Autowired自动注入StoreUserMapper
  • 异常处理: 所有方法都包含完善的异常处理,确保不会抛出异常
  • 日志记录: 详细的日志记录,便于调试和问题排查
  • 多种获取方式: 支持从Token获取基本信息,或从数据库查询完整信息

类结构

@Slf4j
@Component
public class LoginUserUtil {
    // 核心方法
    public static Integer getCurrentUserId()           // 获取用户ID
    public static String getCurrentUserPhone()         // 获取手机号
    public static String getCurrentUserType()          // 获取用户类型
    public static JSONObject getCurrentUserInfo()      // 获取Token中的用户信息
    public static StoreUser getCurrentStoreUser()      // 获取完整用户信息(数据库)
    public static StoreUser getCurrentStoreUserByPhone() // 根据手机号获取用户信息
    
    // 辅助方法
    public static boolean isCurrentUser(Integer userId)  // 验证是否为当前用户
    public static boolean isLogin()                      // 验证是否已登录
    public static boolean isStorePlatformUser()          // 验证是否为商户平台用户
    
    // 便捷方法
    public static Integer getCurrentStoreId()            // 获取门店ID
    public static String getCurrentNickName()            // 获取昵称
    public static String getCurrentName()                // 获取真实姓名
}

方法详解

1. getCurrentUserId()

获取当前登录用户的ID(从Token中获取,无需查询数据库)

/**
 * 获取当前登录用户的ID
 * @return 用户ID,如果未登录返回null
 */
public static Integer getCurrentUserId()

使用示例:

Integer userId = LoginUserUtil.getCurrentUserId();
if (userId != null) {
    System.out.println("当前用户ID: " + userId);
} else {
    System.out.println("用户未登录");
}

返回值:

  • 成功: 返回用户ID(Integer)
  • 未登录: 返回null

性能: ⚡ 快速(只解析Token,不查询数据库)


2. getCurrentUserPhone()

获取当前登录用户的手机号(从Token中获取)

/**
 * 获取当前登录用户的手机号
 * @return 手机号,如果未登录返回null
 */
public static String getCurrentUserPhone()

使用示例:

String phone = LoginUserUtil.getCurrentUserPhone();
if (phone != null) {
    System.out.println("当前用户手机号: " + phone);
}

返回值:

  • 成功: 返回手机号(String)
  • 未登录: 返回null

性能: ⚡ 快速(只解析Token)


3. getCurrentUserType()

获取当前登录用户的用户类型(从Token中获取)

/**
 * 获取当前登录用户的用户类型
 * @return 用户类型,如果未登录返回null
 */
public static String getCurrentUserType()

使用示例:

String userType = LoginUserUtil.getCurrentUserType();
if ("storePlatform".equals(userType)) {
    System.out.println("商户平台用户");
}

返回值:

  • 成功: 返回用户类型(String),如 "storePlatform"
  • 未登录: 返回null

性能: ⚡ 快速(只解析Token)


4. getCurrentUserInfo()

获取当前登录用户的Token信息(JSONObject格式)

/**
 * 获取当前登录用户的Token信息(JSONObject格式)
 * @return 用户信息JSONObject,包含userId、phone、userType等字段
 */
public static JSONObject getCurrentUserInfo()

使用示例:

JSONObject userInfo = LoginUserUtil.getCurrentUserInfo();
if (userInfo != null) {
    Integer userId = userInfo.getInteger("userId");
    String phone = userInfo.getString("phone");
    String userType = userInfo.getString("userType");
    
    System.out.println("用户ID: " + userId);
    System.out.println("手机号: " + phone);
    System.out.println("用户类型: " + userType);
}

返回值:

  • 成功: 返回包含用户信息的JSONObject
  • 未登录: 返回null

包含字段:

  • userId: 用户ID
  • phone: 手机号
  • userType: 用户类型

性能: ⚡ 快速(只解析Token)


5. getCurrentStoreUser()

获取当前登录用户的完整商户用户信息(从数据库查询)

/**
 * 获取当前登录用户的完整商户用户信息(从数据库查询)
 * @return StoreUser对象,如果未登录或查询失败返回null
 */
public static StoreUser getCurrentStoreUser()

使用示例:

StoreUser storeUser = LoginUserUtil.getCurrentStoreUser();
if (storeUser != null) {
    System.out.println("用户ID: " + storeUser.getId());
    System.out.println("手机号: " + storeUser.getPhone());
    System.out.println("昵称: " + storeUser.getNickName());
    System.out.println("真实姓名: " + storeUser.getName());
    System.out.println("门店ID: " + storeUser.getStoreId());
    System.out.println("账户余额: " + storeUser.getMoney());
}

返回值:

  • 成功: 返回StoreUser对象(包含所有字段)
  • 未登录: 返回null
  • 查询失败: 返回null

性能: 🐢 较慢(需要查询数据库)

注意:

  • 适用于需要完整用户信息的场景
  • 会产生数据库查询,建议在需要时才调用

6. getCurrentStoreUserByPhone()

根据手机号获取商户用户信息(从数据库查询)

/**
 * 根据手机号获取商户用户信息
 * @return StoreUser对象,如果未登录或查询失败返回null
 */
public static StoreUser getCurrentStoreUserByPhone()

使用示例:

StoreUser storeUser = LoginUserUtil.getCurrentStoreUserByPhone();
if (storeUser != null) {
    System.out.println("用户信息: " + storeUser);
}

返回值:

  • 成功: 返回StoreUser对象
  • 未登录: 返回null
  • 查询失败: 返回null

性能: 🐢 较慢(需要查询数据库)

与 getCurrentStoreUser() 的区别:

  • getCurrentStoreUser(): 根据用户ID查询(主键查询,更快)
  • getCurrentStoreUserByPhone(): 根据手机号查询(索引查询,稍慢)

7. isCurrentUser(Integer userId)

验证当前登录用户是否为指定用户

/**
 * 验证当前登录用户是否为指定用户
 * @param userId 要验证的用户ID
 * @return true-是当前用户, false-不是当前用户
 */
public static boolean isCurrentUser(Integer userId)

使用示例:

Integer targetUserId = 12345;
if (LoginUserUtil.isCurrentUser(targetUserId)) {
    System.out.println("是当前用户,允许操作");
} else {
    System.out.println("不是当前用户,拒绝操作");
}

使用场景:

  • 权限验证:确保用户只能修改自己的信息
  • 安全检查:防止用户操作其他用户的数据

返回值:

  • true: 是当前登录用户
  • false: 不是当前登录用户或未登录

8. isLogin()

验证当前用户是否已登录

/**
 * 验证当前用户是否已登录
 * @return true-已登录, false-未登录
 */
public static boolean isLogin()

使用示例:

if (LoginUserUtil.isLogin()) {
    System.out.println("用户已登录");
} else {
    System.out.println("用户未登录");
}

返回值:

  • true: 已登录
  • false: 未登录

9. isStorePlatformUser()

验证当前用户类型是否为web端商户平台

/**
 * 验证当前用户类型是否为web端商户平台
 * @return true-是商户平台用户, false-不是
 */
public static boolean isStorePlatformUser()

使用示例:

if (LoginUserUtil.isStorePlatformUser()) {
    System.out.println("商户平台用户,允许访问");
} else {
    System.out.println("非商户平台用户,拒绝访问");
}

返回值:

  • true: 用户类型为 storePlatform
  • false: 用户类型不是 storePlatform 或未登录

10. getCurrentStoreId()

获取当前登录用户的门店ID

/**
 * 获取当前登录用户的门店ID
 * @return 门店ID,如果未登录或用户无门店返回null
 */
public static Integer getCurrentStoreId()

使用示例:

Integer storeId = LoginUserUtil.getCurrentStoreId();
if (storeId != null) {
    System.out.println("当前用户的门店ID: " + storeId);
}

返回值:

  • 成功: 返回门店ID(Integer)
  • 未登录: 返回null
  • 用户无门店: 返回null

性能: 🐢 较慢(需要查询数据库)


11. getCurrentNickName()

获取当前登录用户的昵称

/**
 * 获取当前登录用户的昵称
 * @return 昵称,如果未登录返回null
 */
public static String getCurrentNickName()

使用示例:

String nickName = LoginUserUtil.getCurrentNickName();
if (nickName != null) {
    System.out.println("欢迎," + nickName);
}

返回值:

  • 成功: 返回昵称(String)
  • 未登录: 返回null

性能: 🐢 较慢(需要查询数据库)


12. getCurrentName()

获取当前登录用户的真实姓名

/**
 * 获取当前登录用户的真实姓名
 * @return 真实姓名,如果未登录返回null
 */
public static String getCurrentName()

使用示例:

String name = LoginUserUtil.getCurrentName();
if (name != null) {
    System.out.println("真实姓名: " + name);
}

返回值:

  • 成功: 返回真实姓名(String)
  • 未登录: 返回null

性能: 🐢 较慢(需要查询数据库)


实际应用场景

场景1: 获取当前用户的基本信息

@RestController
@RequestMapping("/user")
public class UserController {
    
    @GetMapping("/profile")
    public R<StoreUser> getUserProfile() {
        // 获取当前登录用户的完整信息
        StoreUser storeUser = LoginUserUtil.getCurrentStoreUser();
        if (storeUser == null) {
            return R.fail("请先登录");
        }
        return R.data(storeUser);
    }
}

场景2: 验证用户权限(只能操作自己的数据)

@Service
public class StoreServiceImpl implements StoreService {
    
    @Override
    public boolean updateStore(Integer storeId, StoreInfo storeInfo) {
        // 获取当前用户的门店ID
        Integer currentStoreId = LoginUserUtil.getCurrentStoreId();
        
        // 验证用户只能修改自己的门店信息
        if (!storeId.equals(currentStoreId)) {
            throw new RuntimeException("您只能修改自己的门店信息");
        }
        
        // 执行更新操作
        return updateStoreInfo(storeInfo);
    }
}

场景3: 自动填充当前用户信息

@Service
public class OrderServiceImpl implements OrderService {
    
    @Override
    public boolean createOrder(Order order) {
        // 自动填充当前用户信息
        Integer userId = LoginUserUtil.getCurrentUserId();
        Integer storeId = LoginUserUtil.getCurrentStoreId();
        
        order.setUserId(userId);
        order.setStoreId(storeId);
        order.setCreateTime(new Date());
        
        return orderMapper.insert(order) > 0;
    }
}

场景4: 根据用户类型返回不同数据

@Service
public class DashboardServiceImpl implements DashboardService {
    
    @Override
    public JSONObject getDashboardData() {
        JSONObject result = new JSONObject();
        
        // 验证用户类型
        if (!LoginUserUtil.isStorePlatformUser()) {
            throw new RuntimeException("只有商户平台用户可以访问");
        }
        
        // 获取用户信息
        Integer storeId = LoginUserUtil.getCurrentStoreId();
        
        // 查询仪表盘数据
        result.put("todayIncome", getTodayIncome(storeId));
        result.put("todayOrderCount", getTodayOrderCount(storeId));
        
        return result;
    }
}

场景5: 日志记录(记录操作人)

@Service
public class AuditLogServiceImpl implements AuditLogService {
    
    @Override
    public void logOperation(String action, String details) {
        AuditLog log = new AuditLog();
        
        // 记录操作人信息
        log.setUserId(LoginUserUtil.getCurrentUserId());
        log.setUserPhone(LoginUserUtil.getCurrentUserPhone());
        log.setUserName(LoginUserUtil.getCurrentName());
        log.setAction(action);
        log.setDetails(details);
        log.setOperateTime(new Date());
        
        auditLogMapper.insert(log);
    }
}

场景6: 条件查询(只查询当前用户的数据)

@Service
public class OrderServiceImpl implements OrderService {
    
    @Override
    public List<Order> getMyOrders(Integer page, Integer size) {
        // 获取当前用户ID
        Integer userId = LoginUserUtil.getCurrentUserId();
        if (userId == null) {
            throw new RuntimeException("请先登录");
        }
        
        // 查询当前用户的订单
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getUserId, userId)
               .orderByDesc(Order::getCreateTime);
        
        return orderMapper.selectPage(new Page<>(page, size), wrapper).getRecords();
    }
}

场景7: 简化Controller代码

之前的写法:

@PostMapping("/updateProfile")
public R<Boolean> updateProfile(@RequestBody StoreUser storeUser) {
    // 需要手动获取用户信息
    JSONObject userInfo = JwtUtil.getCurrentUserInfo();
    if (userInfo == null) {
        return R.fail("请先登录");
    }
    Integer userId = userInfo.getInteger("userId");
    storeUser.setId(userId);
    
    boolean success = storeUserService.updateById(storeUser);
    return success ? R.success("修改成功") : R.fail("修改失败");
}

使用工具类后:

@PostMapping("/updateProfile")
public R<Boolean> updateProfile(@RequestBody StoreUser storeUser) {
    // 直接获取用户ID
    Integer userId = LoginUserUtil.getCurrentUserId();
    if (userId == null) {
        return R.fail("请先登录");
    }
    storeUser.setId(userId);
    
    boolean success = storeUserService.updateById(storeUser);
    return success ? R.success("修改成功") : R.fail("修改失败");
}

性能对比

方法 性能 是否查询数据库 适用场景
getCurrentUserId() ⚡⚡⚡ 极快 ❌ 否 只需要用户ID
getCurrentUserPhone() ⚡⚡⚡ 极快 ❌ 否 只需要手机号
getCurrentUserType() ⚡⚡⚡ 极快 ❌ 否 验证用户类型
getCurrentUserInfo() ⚡⚡⚡ 极快 ❌ 否 需要Token中的多个字段
getCurrentStoreUser() 🐢 较慢 ✅ 是 需要完整用户信息
getCurrentStoreUserByPhone() 🐢 较慢 ✅ 是 根据手机号查询
getCurrentStoreId() 🐢 较慢 ✅ 是 只需要门店ID
getCurrentNickName() 🐢 较慢 ✅ 是 只需要昵称
getCurrentName() 🐢 较慢 ✅ 是 只需要真实姓名

优化建议:

  • ✅ 优先使用不查询数据库的方法(getCurrentUserId()getCurrentUserPhone()等)
  • ✅ 如果需要多个用户字段,使用getCurrentStoreUser()一次性获取,避免多次查询
  • ✅ 不要在循环中调用需要查询数据库的方法

注意事项

1. 空值处理

所有方法在获取失败时都返回null,使用时需要判空:

Integer userId = LoginUserUtil.getCurrentUserId();
if (userId != null) {
    // 处理业务逻辑
} else {
    // 处理未登录情况
}

2. 异常处理

工具类内部已处理所有异常,不会向外抛出异常,确保调用安全。

3. 静态方法限制

由于使用静态方法,需要通过@Autowired注入StoreUserMapper到静态字段。这是通过@Component和setter方法实现的。

4. 性能考虑

  • 频繁调用: 如果需要频繁获取用户信息,建议在Service层缓存
  • 数据库查询: 避免在循环中调用需要查询数据库的方法

5. 线程安全

工具类是线程安全的,可以在多线程环境下使用。


@LoginRequired 注解配合使用

LoginUserUtil@LoginRequired 注解配合使用效果更佳:

@RestController
@RequestMapping("/store")
public class StoreController {
    
    @LoginRequired  // AOP切面验证登录
    @GetMapping("/myStore")
    public R<StoreInfo> getMyStore() {
        // 登录验证已通过,直接获取门店ID
        Integer storeId = LoginUserUtil.getCurrentStoreId();
        StoreInfo storeInfo = storeService.getById(storeId);
        return R.data(storeInfo);
    }
}

配置要求

1. Spring Bean注册

工具类使用@Component注解,需要被Spring扫描到:

@Component  // 必须
public class LoginUserUtil {
    // ...
}

2. 包扫描配置

确保LoginUserUtil所在的包被Spring Boot扫描:

@SpringBootApplication
@ComponentScan(basePackages = {"shop.alien.storeplatform"})
public class Application {
    // ...
}

3. Mapper依赖

确保StoreUserMapper已注册为Spring Bean:

@Mapper
public interface StoreUserMapper extends BaseMapper<StoreUser> {
}

常见问题

Q1: 为什么有时返回null?

原因:

  1. 用户未登录(Token不存在或无效)
  2. Token已过期
  3. 用户在数据库中不存在
  4. 网络或数据库异常

解决方案:

  • 使用前先判断是否已登录:LoginUserUtil.isLogin()
  • 检查日志中的错误信息

Q2: 如何在非Controller层使用?

答案: 工具类可以在任何Spring管理的Bean中使用:

@Service
public class MyService {
    
    public void someMethod() {
        Integer userId = LoginUserUtil.getCurrentUserId();
        // 使用userId
    }
}

Q3: 性能是否有问题?

答案:

  • Token解析方法(如getCurrentUserId())性能很高,可以频繁调用
  • 数据库查询方法(如getCurrentStoreUser())性能较低,建议缓存结果

Q4: 如何缓存用户信息?

建议方案:

@Service
public class MyService {
    
    private StoreUser currentUser;
    
    public void processOrder() {
        // 第一次获取
        if (currentUser == null) {
            currentUser = LoginUserUtil.getCurrentStoreUser();
        }
        
        // 后续使用缓存的数据
        Integer storeId = currentUser.getStoreId();
        // ...
    }
}

或使用ThreadLocal缓存(适用于同一次请求)。


更新日志

2025-11-17

新增工具类:

  • ✅ 创建LoginUserUtil工具类

核心功能:

  • ✅ 获取当前登录用户ID、手机号、用户类型
  • ✅ 获取Token中的用户信息(JSONObject)
  • ✅ 从数据库查询完整用户信息
  • ✅ 验证用户登录状态
  • ✅ 验证用户类型
  • ✅ 验证是否为当前用户
  • ✅ 获取门店ID、昵称、姓名等便捷方法

技术特点:

  • ✅ 静态方法,方便调用
  • ✅ 完善的异常处理
  • ✅ 详细的日志记录
  • ✅ 支持多种获取方式

开发人员: ssk


文档版本: v1.0
最后更新: 2025-11-17
维护人员: ssk