用户管理系统 05 实现后端注册功能 | Java新手实战 | 最小架构 | 期末实训 | Java+SpringBoot+Vue3

用户管理系统 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) {
    // 统一异常处理
    // 事务自动回滚
}

🎯🎯🎯 核心知识点总结

✅ 注册功能完整流程

  1. 参数校验 - 确保数据合法性
  2. 唯一性校验 - 防止数据重复
  3. 密码加密 - 保障数据安全
  4. 数据入库 - 完成持久化存储

✅ 企业级开发技能

  1. BCrypt加密 - 密码安全存储
  2. 事务管理 - 数据一致性保障
  3. 分层设计 - 代码结构清晰
  4. 异常处理 - 系统健壮性提升

🚀🚀🚀 立即动手实践

操作步骤:

  1. 更新代码:按照文章实现注册功能
  2. 添加依赖:在pom.xml中加入BCrypt
  3. 测试验证:使用Postman进行功能测试
  4. 数据库检查:确认密码加密存储正确

常见问题解决:

  • 依赖下载失败:检查Maven配置,使用阿里云镜像
  • 事务不生效:确保方法为public,且异常被抛出
  • 加密验证失败:确认使用BCrypt.checkpw()方法

📌📌📌 下一篇预告

第六篇:用户管理功能实现

  • 查询用户列表(分页显示)
  • 新增用户(表单提交)
  • 编辑用户(信息修改)
  • 删除用户(单条删除)

💫💫 本章总结

通过本章学习,我们完成了:

✅ 功能实现成果

  1. 完整的用户注册功能 - 从接口定义到数据存储
  2. 安全的密码处理 - BCrypt加密保障数据安全
  3. 健壮的异常处理 - 事务管理保证数据一致性
  4. 完善的参数校验 - 提升系统鲁棒性

💡💡 新手成长收获

  1. 掌握企业级密码加密技术
  2. 理解事务管理的重要性
  3. 学会分层架构的实际应用
  4. 具备完整的业务功能开发能力

🎯🎯 实践价值

这个注册功能直接可用于真实项目,为你后续的求职和项目开发打下坚实基础!


💬💬 互动话题:你在实现注册功能时遇到了哪些问题?或者对密码加密、事务管理有什么疑问?欢迎在评论区留言交流!

🚀🚀 行动建议:立即动手实现代码,遇到问题随时提问,我们一起解决!


关注B站"90后小陈老师 ",私信回复"Java"获取资料!

相关推荐
武子康1 分钟前
大数据-189 Nginx JSON 日志接入 ELK:ZK+Kafka+Elasticsearch 7.3.0+Kibana 实战搭建
大数据·后端·elasticsearch
码海踏浪2 分钟前
JMeter 时间函数合集
开发语言·python
麦麦鸡腿堡3 分钟前
Java_反射暴破创建对象与访问类中的成员
java·开发语言
不会c嘎嘎4 分钟前
深入理解QT之信号和槽
开发语言·qt
SunnyDays10114 分钟前
Python 实现 PDF 文档压缩:完整指南
linux·开发语言·python
大海星辰7985 分钟前
工厂模式与策略模式的深度实践:从代码优化到架构思考
java·架构·策略模式
Cx330❀5 分钟前
《C++ 动态规划》第001-002题:第N个泰波拉契数,三步问题
开发语言·c++·算法·动态规划
神仙别闹6 分钟前
基于Qt5(C++)+SQLite 开发的一个小巧精美的本地音乐播放器
开发语言·c++·qt
Jack_abu6 分钟前
详解java中的线程间协作工具:CountDownLatch,Semaphore,CyclicBarrier(二)
java·并发编程·juc
差点GDP7 分钟前
C语言常用编译命令和示例
c语言·开发语言