协享云图分析--3用户模块
用户表
-- 用户表
create table if not exists user
(id bigint auto_increment comment 'id' primary key,userAccount varchar(256) not null comment '账号',userPassword varchar(512) not null comment '密码',userName varchar(256) null comment '用户昵称',userAvatar varchar(1024) null comment '用户头像',userProfile varchar(512) null comment '用户简介',userRole varchar(256) default 'user' not null comment '用户角色:user/admin',editTime datetime default CURRENT_TIMESTAMP not null comment '编辑时间',createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',isDelete tinyint default 0 not null comment '是否删除',UNIQUE KEY uk_userAccount (userAccount),INDEX idx_userName (userName)
) comment '用户' collate = utf8mb4_unicode_ci;
1. UNIQUE KEY uk_userAccount (userAccount)
- 定义了一个唯一约束(Unique Key),确保userAccount字段的值在表中必须唯一。
- 如果尝试插入或更新一条重复的userAccount值,数据库会报错。
2. INDEX idx_userName (userName)
- 定义了一个普通索引(Index),用于加速基于userName字段的查询操作。
- 索引不会强制唯一性,但可以显著提高查询性能,尤其是在大数据量的情况下。
用户登录流程
@startuml
actor Frontend
participant Server
participant BrowserFrontend -> Server: 建立连接
Server -> Frontend: 创建匿名Session,返回Session ID
Frontend -> Server: 提交登录信息(用户名 & 密码)
Server -> Server: 验证登录信息
Server -> Server: 更新Session,存储用户信息
Server -> Frontend: 返回Set - Cookie指令(Session ID)
Frontend -> Browser: 浏览器保存Cookie(Session ID)
Frontend -> Server: 后续请求时自动附带Cookie
Server -> Server: 提取Cookie,查找对应Session
Server -> Server: 从Session中获取用户信息
Server -> Frontend: 返回处理结果(如页面或数据)
@enduml
绘图代码UML
绘图网站
PlantUML Web Server
这是一张描述用户登录及后续会话管理流程的时序图。
图中包含前端(Frontend)、服务器(Server)和浏览器(Browser)三个角色 ,具体流程如下:
- 建立连接:前端与服务器建立连接。
- 创建匿名会话:服务器创建匿名 Session,并向前端返回 Session ID。
- 提交登录信息:前端将用户名和密码等登录信息提交给服务器。
- 验证与更新:服务器验证登录信息,验证通过后更新 Session,存储用户信息。
- 设置 Cookie:服务器向前端返回 Set - Cookie 指令,其中包含 Session ID。
- 保存 Cookie:前端收到指令后,浏览器保存该 Cookie(Session ID) 。
- 后续请求:后续浏览器向服务器发起请求时,会自动附带该 Cookie。
- 获取用户信息:服务器提取 Cookie,查找对应的 Session,从中获取用户信息。
- 返回结果:服务器将处理结果(如页面或数据)返回给前端。
实体类
定义了一个名为User的类,并实现了Serializable接口。
Serializable接口
实现Serializable接口表示该类的对象可以被序列化,即可以将对象的状态保存到文件或通过网络传输。
雪花算法
@TableId(type = IdType.ASSIGN_ID)
@TableId 注解标识该字段为数据库表的主键。
type = IdType.ASSIGN_ID 指定主键生成策略为 ASSIGN_ID,通常表示使用分布式唯一ID生成器(如Snowflake算法)生成主键。
雪花算法(Snowflake Algorithm)是由Twitter提出的一种分布式唯一ID生成算法,能够生成全局唯一的64位整数ID。其结构通常包括时间戳、机器ID、数据中心ID和序列号等部分,保证了在分布式系统中的唯一性。
在提供的代码中,雪花算法的体现如下:
第10行:@TableId(type = IdType.ASSIGN_ID) 这里指定了主键生成策略为 IdType.ASSIGN_ID,该策略通常基于雪花算法实现,用于生成分布式环境下的唯一ID。
枚举类
UserRoleEnum用户角色枚举
定义了一个名为 UserRoleEnum 的枚举类,用于表示用户角色。
定义了三种用户角色:普通用户(USER)、会员(VIP)和管理员(ADMIN),每种角色包含文本描述和值。
提供了一个静态方法 getEnumByValue,根据传入的值查找并返回对应的枚举对象,若未找到或值为空,则返回 null。
model.dto.user
UserRegisterRequest用户注册请求
service
UserService
定义了一个名为 UserService 的接口,用于处理用户相关的业务逻辑。
- 用户注册:通过校验账户和密码完成新用户注册。
- 用户登录:验证账户和密码,并返回脱敏后的用户信息。
- 密码加密:提供密码加密功能。
- 获取当前登录用户:从请求中提取登录用户信息。
- 脱敏用户信息:生成脱敏后的用户信息或列表。
- 用户注销:清除登录状态。
- 条件查询:构建用户查询条件。
- 管理员判断:检查用户是否为管理员。
- 会员兑换:通过会员码兑换会员资格。
IService
这段代码定义了一个名为UserService的接口,该接口继承了泛型接口IService<User>。这意味着UserService接口将用于处理与User实体相关的业务逻辑,并且可以使用IService中定义的所有方法。
IService<User> 是 MyBatis-Plus 框架提供的一个通用服务接口,它继承自 IService,并针对泛型实体类(这里是 User)提供了丰富的 CRUD 方法。以下是 IService 中常见的方法列表:
1. 基本增删改查
- boolean save(User entity):新增记录
- boolean removeById(Serializable id):根据 ID 删除记录
- boolean updateById(User entity):根据 ID 修改记录
- User getById(Serializable id):根据 ID 查询记录
2. 批量操作
- boolean saveBatch(Collection<User> entities):批量新增
- boolean removeBatchByIds(Collection<? extends Serializable> ids):批量删除
- boolean updateBatchById(Collection<User> entities):批量修改
3. 查询相关
- List<User> list():查询所有记录
- List<User> listByIds(Collection<? extends Serializable> ids):根据多个 ID 查询记录
- IPage<User> page(Page<User> page):分页查询
4. 统计相关
- long count():统计记录总数
这些方法可以直接通过 IService 的实现类(如 ServiceImpl)使用。
UserServiceImpl
@Overridepublic long userRegister(String userAccount, String userPassword, String checkPassword) {// 1. 校验参数if (StrUtil.hasBlank(userAccount, userPassword, checkPassword)) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");}if (userAccount.length() < 4) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");}if (userPassword.length() < 8 || checkPassword.length() < 8) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");}if (!userPassword.equals(checkPassword)) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");}// 2. 检查用户账号是否和数据库中已有的重复QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("userAccount", userAccount);long count = this.baseMapper.selectCount(queryWrapper);if (count > 0) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");}// 3. 密码一定要加密String encryptPassword = getEncryptPassword(userPassword);// 4. 插入数据到数据库中User user = new User();user.setUserAccount(userAccount);user.setUserPassword(encryptPassword);user.setUserName("无名");user.setUserRole(UserRoleEnum.USER.getValue());boolean saveResult = this.save(user);if (!saveResult) {throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败,数据库错误");}return user.getId();}