用户管理系统 05 实现后端注册功能 Java新手实战 最小架构 期末实训 Java+SpringBoot+Vue3
B站视频教程:https://space.bilibili.com/3493114532596161/lists/6609623?type=season
关注B站"90后小陈老师 ",私信回复"Java"获取资料!
手把手教你实现安全可靠的用户注册功能,掌握企业级开发核心技能
本文是用户管理系统实战系列的第五篇,专为Java新手设计。我们将采用MVP最小架构原则,实现用户注册功能,让你快速掌握企业级开发的核心流程。
🎯🎯🎯 本章学习目标
- ✅ 掌握用户注册的完整业务流程
- ✅ 学会密码加密存储技术
- ✅ 理解手机号唯一性校验
- ✅ 掌握事务管理的基本用法
🏗🏗🏗️ 注册功能架构设计
注册流程全景图
前端请求
↓
Controller层(参数基础校验)
↓
Service层(核心业务逻辑)
├── 参数格式校验
├── 手机号唯一性检查
├── 密码加密处理
├── 用户数据入库
└└── 返回注册结果
↓
数据库持久化存储
🔧🔧 代码实现详解
1. Controller层实现 - 注册入口
位置 :src/main/java/com/jackson/usermanager/controller/UserController.java
java
package com.jackson.usermanager.controller;
import com.jackson.usermanager.common.Result;
import com.jackson.usermanager.model.domain.User;
import com.jackson.usermanager.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
/**
* 用户注册接口
* @param user 用户信息
* @return 注册结果
*/
@PostMapping("/register")
public Result<String> register(@RequestBody User user) {
// 1. 基础参数校验
if (user == null || !StringUtils.hasText(user.getPhone())
|| !StringUtils.hasText(user.getPwd())) {
return Result.error("手机号和密码不能为空");
}
// 2. 调用Service层处理注册逻辑
return userService.register(user);
}
// 上一章的登录方法保持不变
@PostMapping("/login")
public Result<User> login(@RequestParam String phone,
@RequestParam String pwd,
HttpSession session) {
// 登录逻辑...
}
}
2. Service层实现 - 核心业务逻辑
位置 :src/main/java/com/jackson/usermanager/service/UserService.java(接口)
java
package com.jackson.usermanager.service;
import com.jackson.usermanager.common.Result;
import com.jackson.usermanager.model.domain.User;
public interface UserService {
/**
* 用户登录
*/
Result<User> login(String phone, String pwd);
/**
* 用户注册
* @param user 用户信息
* @return 注册结果
*/
Result<String> register(User user);
}
位置 :src/main/java/com/jackson/usermanager/service/impl/UserServiceImpl.java(实现类)
java
package com.jackson.usermanager.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jackson.usermanager.common.Result;
import com.jackson.usermanager.mapper.UserMapper;
import com.jackson.usermanager.model.domain.User;
import com.jackson.usermanager.service.UserService;
import lombok.RequiredArgsConstructor;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.Date;
import java.util.regex.Pattern;
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
private final UserMapper userMapper;
// 常量定义
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
private static final int MIN_PASSWORD_LENGTH = 8;
/**
* 用户注册实现
*/
@Override
@Transactional
public Result<String> register(User user) {
try {
// 1. 参数校验
Result<String> validateResult = validateRegisterParams(user);
if (validateResult.getCode() != 200) {
return validateResult;
}
// 2. 检查手机号是否已注册
if (isPhoneRegistered(user.getPhone())) {
return Result.error("该手机号已被注册");
}
// 3. 密码加密处理
String encryptedPassword = encryptPassword(user.getPwd());
user.setPwd(encryptedPassword);
// 4. 设置默认值
setDefaultValues(user);
// 5. 保存用户信息
int result = userMapper.insert(user);
if (result <= 0) {
return Result.error("注册失败,请重试");
}
return Result.success("注册成功");
} catch (Exception e) {
// 事务会自动回滚
return Result.error("系统异常:" + e.getMessage());
}
}
/**
* 注册参数校验
*/
private Result<String> validateRegisterParams(User user) {
// 手机号格式校验
if (!patternMatches(PHONE_REGEX, user.getPhone())) {
return Result.error("手机号格式不正确");
}
// 密码强度校验
if (user.getPwd().length() < MIN_PASSWORD_LENGTH) {
return Result.error("密码长度不能少于8位");
}
// 昵称非空校验
if (!StringUtils.hasText(user.getNickName())) {
return Result.error("昵称不能为空");
}
return Result.success("参数校验通过");
}
/**
* 检查手机号是否已注册
*/
private boolean isPhoneRegistered(String phone) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("phone", phone);
Long count = userMapper.selectCount(queryWrapper);
return count != null && count > 0;
}
/**
* 密码加密处理
*/
private String encryptPassword(String plainPassword) {
return BCrypt.hashpw(plainPassword, BCrypt.gensalt());
}
/**
* 设置用户默认值
*/
private void setDefaultValues(User user) {
// 默认角色:普通用户
if (user.getRole() == null) {
user.setRole(0);
}
// 默认状态:正常
if (user.getStatus() == null) {
user.setStatus(0);
}
// 设置当前时间
user.setCreateTime(new Date());
user.setUpdateTime(new Date());
}
/**
* 正则校验工具方法
*/
private boolean patternMatches(String regex, String input) {
if (!StringUtils.hasText(input)) {
return false;
}
Pattern pattern = Pattern.compile(regex);
return pattern.matcher(input).matches();
}
// 上一章的登录方法需要更新密码验证逻辑
@Override
public Result<User> login(String phone, String pwd) {
// 前面的校验逻辑不变...
// 更新密码验证逻辑
if (!validatePassword(pwd, user.getPwd())) {
return Result.error("密码错误");
}
// 后续逻辑不变...
}
/**
* 更新密码验证方法(支持BCrypt加密验证)
*/
private boolean validatePassword(String inputPassword, String storedPassword) {
return BCrypt.checkpw(inputPassword, storedPassword);
}
}
3. 添加BCrypt密码加密依赖
位置 :pom.xml
xml
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
⚙⚙⚙️ 配置文件更新
application.yml 完整配置
server:
port: 8080
servlet:
context-path: /api
session:
timeout: 1800
spring:
application:
name: user-manager
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/user-manager?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
# MyBatis配置
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: status # 逻辑删除字段
logic-delete-value: 1 # 逻辑删除值
logic-not-delete-value: 0 # 逻辑未删除值
# 日志配置
logging:
level:
com.jackson.usermanager: debug
🧪🧪🧪 功能测试指南
1. 使用Postman测试注册接口
请求示例:
POST http://localhost:8080/api/user/register
Content-Type: application/json
{
"nickName": "测试用户",
"phone": "13800138000",
"pwd": "12345678"
}
预期响应:
{
"code": 200,
"message": "注册成功",
"data": null
}
2. 测试用例覆盖场景
| 测试场景 | 输入数据 | 预期结果 |
|---|---|---|
| 正常注册 | 正确格式数据 | 注册成功 |
| 手机号为空 | 空手机号 | "手机号和密码不能为空" |
| 密码过短 | 密码"123" | "密码长度不能少于8位" |
| 手机号格式错误 | "1234567890" | "手机号格式不正确" |
| 重复注册 | 已注册手机号 | "该手机号已被注册" |
🔒🔒 安全特性详解
1. 密码加密 - BCrypt技术优势
// 加密过程
String hashed = BCrypt.hashpw(plainPassword, BCrypt.gensalt());
// 验证过程
boolean isValid = BCrypt.checkpw(inputPassword, storedPassword);
BCrypt优势:
- ✅ 盐值加密:每次加密结果不同,防止彩虹表攻击
- ✅ 自适应成本:可调整计算强度,抵御硬件破解
- ✅ 行业标准:广泛用于企业级应用
2. 事务管理保证数据一致性
@Transactional
public Result<String> register(User user) {
// 如果任何一步失败,整个操作回滚
// 保证不会出现数据不一致的情况
}
🌟🌟 新手学习要点
1. 分层架构理解
Controller → Service → Mapper → Database
↓ ↓ ↓ ↓
请求接收 业务逻辑 数据操作 数据存储
2. 重要注解掌握
@RestController:声明Restful控制器@Transactional:声明式事务管理@RequestBody:接收JSON格式参数@RequiredArgsConstructor:Lombok构造器注入
3. 异常处理策略
try {
// 业务逻辑
} catch (Exception e) {
// 统一异常处理
// 事务自动回滚
}
🎯🎯🎯 核心知识点总结
✅ 注册功能完整流程
- 参数校验 - 确保数据合法性
- 唯一性校验 - 防止数据重复
- 密码加密 - 保障数据安全
- 数据入库 - 完成持久化存储
✅ 企业级开发技能
- BCrypt加密 - 密码安全存储
- 事务管理 - 数据一致性保障
- 分层设计 - 代码结构清晰
- 异常处理 - 系统健壮性提升
🚀🚀🚀 立即动手实践
操作步骤:
- 更新代码:按照文章实现注册功能
- 添加依赖:在pom.xml中加入BCrypt
- 测试验证:使用Postman进行功能测试
- 数据库检查:确认密码加密存储正确
常见问题解决:
- ❓ 依赖下载失败:检查Maven配置,使用阿里云镜像
- ❓ 事务不生效:确保方法为public,且异常被抛出
- ❓ 加密验证失败:确认使用BCrypt.checkpw()方法
📌📌📌 下一篇预告
第六篇:用户管理功能实现
- 查询用户列表(分页显示)
- 新增用户(表单提交)
- 编辑用户(信息修改)
- 删除用户(单条删除)
💫💫 本章总结
通过本章学习,我们完成了:
✅ 功能实现成果
- 完整的用户注册功能 - 从接口定义到数据存储
- 安全的密码处理 - BCrypt加密保障数据安全
- 健壮的异常处理 - 事务管理保证数据一致性
- 完善的参数校验 - 提升系统鲁棒性
💡💡 新手成长收获
- 掌握企业级密码加密技术
- 理解事务管理的重要性
- 学会分层架构的实际应用
- 具备完整的业务功能开发能力
🎯🎯 实践价值
这个注册功能直接可用于真实项目,为你后续的求职和项目开发打下坚实基础!
💬💬 互动话题:你在实现注册功能时遇到了哪些问题?或者对密码加密、事务管理有什么疑问?欢迎在评论区留言交流!
🚀🚀 行动建议:立即动手实现代码,遇到问题随时提问,我们一起解决!
关注B站"90后小陈老师 ",私信回复"Java"获取资料!