SpringBoot 3小时实战入门:从零构建用户管理Web应用

📅 2026/7/21 22:39:06
SpringBoot 3小时实战入门:从零构建用户管理Web应用
这次我们来看一个 SpringBoot 学习项目。对于很多刚接触 Java 后端开发的同学来说SpringBoot 是一个绕不开的核心框架但官方文档庞大网上教程零散常常让人不知从何下手。这个项目或视频教程的核心目标很直接通过一套结构化的实战内容帮助学习者在短时间内如3小时掌握 SpringBoot 的核心开发流程。它最值得关注的几个特点是实战驱动不是空讲理论技术栈完整覆盖了从项目创建、数据库操作到缓存、权限等企业级常用功能门槛明确要求你具备 Java 和 Maven 基础结果可验证最终你能得到一个可以运行、具备基础 CRUD 和接口文档的完整项目。本文将带你拆解这套学习路径从环境准备、项目搭建到功能模块开发、接口测试最后部署运行让你清楚每一步要做什么、会遇到什么问题以及如何解决。1. 核心能力速览能力项说明学习目标3小时内快速上手 SpringBoot 基础开发构建一个具备完整功能模块的 Web 应用。核心技术栈SpringBoot, Maven, MySQL, Redis, MyBatis-Plus, 接口文档如 Swagger/Knife4j。涉及功能模块用户管理、权限认证、数据增删改查CRUD、缓存应用、接口文档生成。前置知识要求基础 Java 语法、Maven 依赖管理概念、对数据库和 HTTP 协议有基本了解。开发环境JDK 8、Maven 3.6、IDEA或 Eclipse、MySQL 5.7/8.0、Redis。项目启动方式通过 IDE 直接运行 SpringBoot 主类或使用mvn spring-boot:run命令启动。是否支持接口 API是项目本身会开发 RESTful API并集成接口文档工具。是否涉及批量任务通常不涉及但数据初始化、缓存预热等场景可引申出批量处理思想。适合场景Java 初学者入门 SpringBoot、应届生准备项目经验、快速构建后端服务原型。2. 适用场景与使用边界这个学习项目非常适合以下几类人群Java 初学者已经学过 Java SE想进入 Web 开发但不知如何开始。转型开发者从其他语言转向 Java需要快速了解 SpringBoot 生态的标准开发模式。在校学生需要完成课程设计或积累实战项目经验应对面试。全栈开发者前端开发者希望了解后端 API 是如何构建和提供的。它能解决的核心问题消除恐惧将庞大的 SpringBoot 生态拆解为可执行的、连续的步骤。建立闭环从创建项目到最终上线本地运行体验完整的开发-测试-调试流程。掌握套路学习如何集成数据库、缓存、接口文档等企业开发中的常见组件。需要注意的使用边界非生产级项目教程项目通常为了教学清晰而简化例如权限认证可能不是最严谨的 RBAC 模型缓存策略也可能较简单。直接用于生产环境需要进一步加固。深度有限3小时课程无法覆盖 SpringBoot 所有高级特性如自动装配原理深度剖析、响应式编程、微服务组件。技术选型固定教程基于特定版本和技术栈如 MyBatis-Plus你需要理解其原理以便未来能替换为 JPA 或其他 ORM 框架。3. 环境准备与前置条件在开始编码之前请确保你的本地开发环境已经就绪。以下是必须和推荐的软件清单必须安装JDK版本 8 或 11LTS 版本为佳。安装后配置JAVA_HOME环境变量。# 检查安装 java -versionMaven版本 3.6 及以上。用于管理项目依赖和构建。# 检查安装 mvn -vIDEIntelliJ IDEA社区版或旗舰版或 Eclipse。IDEA 对 SpringBoot 支持更好推荐使用。MySQL版本 5.7 或 8.0。安装并启动服务记住 root 密码。Redis用于缓存实践。Windows 用户可下载安装包或使用 WSLLinux/macOS 通过包管理器安装。推荐安装数据库客户端Navicat、DBeaver 或 MySQL Workbench用于直观操作数据库。API 测试工具Postman 或 Insomnia用于测试编写的接口。Git用于版本管理也便于从 GitHub 等平台克隆示例代码。环境检查清单[ ] JDK 版本符合要求环境变量配置正确。[ ] Maven 安装成功配置了国内镜像源如阿里云镜像以加速依赖下载。[ ] IDEA 中已配置好 JDK 和 Maven 路径。[ ] MySQL 服务正在运行可以通过客户端连接。[ ] Redis 服务正在运行可以通过redis-cli ping命令测试。4. 项目创建与初始化我们将使用 Spring Initializr 来快速生成项目骨架这是最标准的方式。步骤 1通过 IDEA 创建项目打开 IDEA选择 “File” - “New” - “Project”。左侧选择 “Spring Initializr”。配置项目元数据Project SDK选择你安装的 JDK。Group通常为公司或组织域名倒写如com.example。Artifact项目名称如springboot-quickstart。TypeMaven。LanguageJava。PackagingJar。Java Version8 或 11。点击 “Next”进入依赖选择页面。在这里勾选我们需要的依赖Spring Web用于构建 Web 应用和 RESTful API。MySQL DriverMySQL 数据库连接驱动。MyBatis Framework或MyBatis-Plus如果教程使用 MyBatis-Plus这里可以先选 MyBatis后续在pom.xml中手动替换为 MyBatis-Plus 依赖。Lombok简化 Java Bean 编写的工具可选但强烈推荐。点击 “Next”选择项目存储路径然后点击 “Finish”。IDEA 会自动下载初始依赖并打开项目。步骤 2调整pom.xml依赖项目创建后打开pom.xml文件。根据教程的技术栈我们可能需要调整或添加一些依赖。?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version !-- 选择一个稳定的版本 -- relativePath/ /parent groupIdcom.example/groupId artifactIdspringboot-quickstart/artifactId version0.0.1-SNAPSHOT/version namespringboot-quickstart/name descriptionSpring Boot quick start project/description properties java.version1.8/java.version mybatis-plus.version3.5.3.1/mybatis-plus.version knife4j.version3.0.3/knife4j.version /properties dependencies !-- Spring Boot Web Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MySQL Driver -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- MyBatis-Plus Starter (替换掉初始的MyBatis) -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version${mybatis-plus.version}/version /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- Redis Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency !-- Knife4j (Swagger增强) 用于接口文档 -- dependency groupIdcom.github.xiaoymin/groupId artifactIdknife4j-spring-boot-starter/artifactId version${knife4j.version}/version /dependency !-- Spring Boot Test Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration excludes exclude groupIdorg.projectlombok/groupId artifactIdlombok/artifactId /exclude /excludes /configuration /plugin /plugins /build /project步骤 3配置应用属性在src/main/resources目录下修改application.yml或application.properties文件配置数据库、Redis 等连接信息。# 应用配置 server: port: 8080 # 数据源配置 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/springboot_db?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_password # 替换为你的MySQL密码 # Redis配置 redis: host: localhost port: 6379 database: 0 # password: 如果Redis有密码请配置 timeout: 3000ms lettuce: pool: max-active: 8 max-wait: -1ms max-idle: 8 min-idle: 0 # MyBatis-Plus 配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL开发时方便生产环境去掉 global-config: db-config: logic-delete-field: deleted # 全局逻辑删除字段名 logic-delete-value: 1 # 逻辑已删除值 logic-not-delete-value: 0 # 逻辑未删除值 # Knife4j 接口文档配置 knife4j: enable: true openapi: title: SpringBoot快速入门项目API文档 description: 这是一个3小时学会SpringBoot的实战项目接口文档 version: v1.0 contact: name: 开发者 setting: language: zh_cn步骤 4创建数据库使用 MySQL 客户端执行以下 SQL 创建数据库和示例表。CREATE DATABASE IF NOT EXISTS springboot_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE springboot_db; CREATE TABLE user ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 密码, email varchar(100) DEFAULT NULL COMMENT 邮箱, phone varchar(20) DEFAULT NULL COMMENT 手机号, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, deleted tinyint(1) DEFAULT 0 COMMENT 逻辑删除标志0-未删除1-已删除, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;5. 核心功能开发与测试项目骨架和配置完成后我们开始开发核心功能模块。遵循分层架构Controller - Service - Mapper - Model。5.1 实体类与 Mapper 开发1. 创建实体类User.java在src/main/java/com/example/entity包下创建。package com.example.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.util.Date; Data TableName(user) // 指定表名 public class User { TableId(type IdType.AUTO) // 主键自增 private Long id; private String username; private String password; private String email; private String phone; TableField(fill FieldFill.INSERT) // 插入时自动填充 private Date createTime; TableField(fill FieldFill.INSERT_UPDATE) // 插入和更新时自动填充 private Date updateTime; TableLogic // 逻辑删除注解 private Integer deleted; }2. 创建 Mapper 接口UserMapper.java在src/main/java/com/example/mapper包下创建。MyBatis-Plus 提供了强大的 BaseMapper。package com.example.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.entity.User; import org.apache.ibatis.annotations.Mapper; Mapper // 标识为MyBatis的MapperSpring会自动扫描 public interface UserMapper extends BaseMapperUser { // 继承 BaseMapper 后基本的 CRUD 方法已自动拥有无需编写 XML }3. 配置元对象处理器为了自动填充createTime和updateTime需要创建一个配置类。package com.example.config; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.util.Date; Component public class MyMetaObjectHandler implements MetaObjectHandler { Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, createTime, Date.class, new Date()); this.strictInsertFill(metaObject, updateTime, Date.class, new Date()); } Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, Date.class, new Date()); } }5.2 Service 层开发创建 Service 接口和实现类在src/main/java/com/example/service包下创建UserService.java接口及其实现类UserServiceImpl.java。// UserService.java package com.example.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.entity.User; public interface UserService extends IServiceUser { // 可以在此定义一些业务特有的方法 boolean register(User user); User login(String username, String password); }// UserServiceImpl.java package com.example.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.entity.User; import com.example.mapper.UserMapper; import com.example.service.UserService; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; import java.nio.charset.StandardCharsets; Service public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { Override public boolean register(User user) { // 1. 检查用户名是否已存在 LambdaQueryWrapperUser queryWrapper new LambdaQueryWrapper(); queryWrapper.eq(User::getUsername, user.getUsername()); User existUser this.getOne(queryWrapper); if (existUser ! null) { throw new RuntimeException(用户名已存在); } // 2. 对密码进行MD5加密实际生产应用更安全的加密方式 String encryptedPassword DigestUtils.md5DigestAsHex(user.getPassword().getBytes(StandardCharsets.UTF_8)); user.setPassword(encryptedPassword); // 3. 保存用户 return this.save(user); } Override public User login(String username, String password) { // 1. 根据用户名查询用户 LambdaQueryWrapperUser queryWrapper new LambdaQueryWrapper(); queryWrapper.eq(User::getUsername, username); User user this.getOne(queryWrapper); if (user null) { throw new RuntimeException(用户名或密码错误); } // 2. 验证密码 String encryptedPassword DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)); if (!user.getPassword().equals(encryptedPassword)) { throw new RuntimeException(用户名或密码错误); } // 3. 返回用户信息注意实际登录应返回Token这里简化 return user; } }5.3 Controller 层与接口文档创建 ControllerUserController.java在src/main/java/com/example/controller包下创建。这里我们集成 Knife4j 注解来生成接口文档。package com.example.controller; import com.example.common.R; import com.example.entity.User; import com.example.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; RestController RequestMapping(/user) Api(tags 用户管理接口) // Knife4j/Swagger 文档分组 public class UserController { Autowired private UserService userService; PostMapping(/register) ApiOperation(用户注册) public RBoolean register(RequestBody User user) { boolean result userService.register(user); return R.success(result); } PostMapping(/login) ApiOperation(用户登录) public RUser login(RequestParam String username, RequestParam String password) { User user userService.login(username, password); return R.success(user); } GetMapping(/{id}) ApiOperation(根据ID查询用户) public RUser getById(PathVariable Long id) { User user userService.getById(id); return R.success(user); } GetMapping(/list) ApiOperation(查询所有用户列表) public RListUser list() { ListUser list userService.list(); return R.success(list); } PostMapping ApiOperation(新增用户) public RBoolean save(RequestBody User user) { boolean result userService.save(user); return R.success(result); } PutMapping ApiOperation(更新用户信息) public RBoolean update(RequestBody User user) { boolean result userService.updateById(user); return R.success(result); } DeleteMapping(/{id}) ApiOperation(删除用户逻辑删除) public RBoolean delete(PathVariable Long id) { boolean result userService.removeById(id); return R.success(result); } }创建统一返回结果类R.java在src/main/java/com/example/common包下创建用于规范 API 响应格式。package com.example.common; import lombok.Data; import java.io.Serializable; Data public class RT implements Serializable { private Integer code; // 状态码200成功其他失败 private String msg; // 提示信息 private T data; // 返回数据 public static T RT success(T data) { RT r new R(); r.setCode(200); r.setMsg(success); r.setData(data); return r; } public static T RT error(String msg) { RT r new R(); r.setCode(500); r.setMsg(msg); return r; } }5.4 功能启动与验证1. 启动项目找到主启动类通常位于src/main/java下的根包如SpringbootQuickstartApplication.java右键运行main方法。控制台看到类似以下日志说明启动成功Started SpringbootQuickstartApplication in 5.123 seconds (JVM running for 6.456)2. 访问接口文档Knife4j 增强了 Swagger 的界面。启动后在浏览器访问http://localhost:8080/doc.html。你将看到一个美观的 API 文档页面里面列出了我们刚编写的所有用户管理接口。3. 使用 Postman 测试接口在 Postman 中测试/user/register接口。请求方法POSTURLhttp://localhost:8080/user/registerHeadersContent-Type: application/jsonBody (raw JSON){ username: testuser, password: 123456, email: testexample.com, phone: 13800138000 }预期响应{ code: 200, msg: success, data: true }此时检查数据库user表应有一条新记录密码已被 MD5 加密。4. 测试登录接口请求方法POSTURLhttp://localhost:8080/user/login?usernametestuserpassword123456预期响应返回用户信息不含密码。5. 测试查询、更新、删除接口。通过这一系列操作你完成了从数据层到表现层的完整链路验证。6. 集成 Redis 实现缓存为了提升性能我们常将热点数据存入 Redis。下面以“根据用户ID查询用户信息”为例添加缓存逻辑。1. 修改 Service 实现在UserServiceImpl中注入RedisTemplate并修改getById方法注意我们直接重写 Service 层的方法Controller 不变。package com.example.service.impl; // ... 其他导入 import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; Service public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { // ... 之前的 register, login 方法 Resource private RedisTemplateString, Object redisTemplate; private static final String USER_CACHE_KEY_PREFIX user:; Override public User getById(Serializable id) { String cacheKey USER_CACHE_KEY_PREFIX id; // 1. 先从缓存中取 User user (User) redisTemplate.opsForValue().get(cacheKey); if (user ! null) { return user; } // 2. 缓存没有查询数据库 user super.getById(id); if (user ! null) { // 3. 存入缓存设置过期时间例如5分钟 redisTemplate.opsForValue().set(cacheKey, user, 5, TimeUnit.MINUTES); } return user; } // 注意在更新和删除用户时需要清除或更新对应的缓存以保证数据一致性。 Override public boolean updateById(User entity) { boolean result super.updateById(entity); if (result) { // 更新成功删除旧缓存 String cacheKey USER_CACHE_KEY_PREFIX entity.getId(); redisTemplate.delete(cacheKey); } return result; } Override public boolean removeById(Serializable id) { boolean result super.removeById(id); if (result) { // 删除成功删除缓存 String cacheKey USER_CACHE_KEY_PREFIX id; redisTemplate.delete(cacheKey); } return result; } }2. 配置 Redis 序列化默认的RedisTemplate序列化方式可能有问题我们创建一个配置类。package com.example.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; Configuration public class RedisConfig { Bean public RedisTemplateString, Object redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(connectionFactory); // 设置 key 的序列化器 template.setKeySerializer(new StringRedisSerializer()); // 设置 value 的序列化器使用 JSON 序列化 template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // 设置 hash key 和 value 的序列化器 template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.afterPropertiesSet(); return template; } }3. 验证缓存效果重启应用。第一次调用GET http://localhost:8080/user/1控制台会打印 SQL 查询日志说明走了数据库。短时间内再次调用同一个接口控制台没有新的 SQL 日志且响应速度极快说明数据从 Redis 缓存中返回。可以使用 Redis 客户端如 Another Redis Desktop Manager连接查看是否存在user:1这个键。7. 接口 API 调用与批量任务思想7.1 接口 API 调用示例我们的服务已经提供了 RESTful API。除了使用 Postman 手动测试在实际开发中你可能需要从其他服务或前端调用这些接口。以下是一个简单的 Python 调用示例import requests import json base_url http://localhost:8080 # 1. 注册用户 register_url f{base_url}/user/register register_data { username: api_user, password: api_pass, email: apiexample.com } register_headers {Content-Type: application/json} register_resp requests.post(register_url, datajson.dumps(register_data), headersregister_headers) print(f注册结果: {register_resp.json()}) # 2. 登录获取用户信息模拟 login_url f{base_url}/user/login login_params { username: api_user, password: api_pass } login_resp requests.post(login_url, paramslogin_params) print(f登录结果: {login_resp.json()})7.2 批量任务处理思想虽然本项目不直接涉及复杂的批量任务如 Spring Batch但我们可以引申出这种思想。例如需要批量导入用户数据。思路提供一个接收文件如 CSV上传的接口。在 Service 层解析文件循环处理每一行数据。对每条数据调用userService.save()或userService.register()。需要考虑事务管理要么全部成功要么全部回滚和性能分批次插入。简单示例伪代码PostMapping(/batchImport) ApiOperation(批量导入用户) public RString batchImport(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return R.error(文件为空); } try { ListUser userList parseCsvFile(file); // 解析CSV到User列表 // 开启事务 TransactionTemplate transactionTemplate ...; transactionTemplate.execute(status - { for (User user : userList) { userService.register(user); // 内部已包含业务校验 } return null; }); return R.success(导入成功共处理 userList.size() 条数据); } catch (Exception e) { return R.error(导入失败: e.getMessage()); } }8. 资源占用与性能观察对于一个 SpringBoot 学习项目性能不是首要关注点但了解基本的资源占用和观察方法是有益的。内存占用一个简单的 SpringBoot 应用启动后JVM 堆内存占用通常在 200MB - 500MB 之间取决于依赖的多少。你可以使用 JVM 参数-Xmx来限制最大堆内存。CPU 占用在空闲状态下 CPU 占用很低。在进行密集的数据库查询或循环处理时CPU 使用率会上升。可以使用topLinux/macOS或任务管理器Windows观察。数据库连接默认的 HikariCP 连接池会维护一些空闲连接。观察 MySQL 的SHOW PROCESSLIST;可以看到来自应用的连接。Redis 连接Spring Boot Data Redis 使用 Lettuce 或 Jedis 客户端会维护一个连接池。简易性能测试使用 Apache JMeter 或简单的脚本对GET /user/{id}接口进行并发请求观察在有缓存和无缓存情况下的 QPS每秒查询率和响应时间差异。你会直观地看到 Redis 缓存带来的性能提升。9. 常见问题与排查方法在学习和部署过程中你可能会遇到以下问题问题现象可能原因排查方式解决方案启动时报java.net.ConnectException: Connection refusedMySQL 或 Redis 服务未启动。检查 MySQL 和 Redis 服务状态。启动相应的服务。启动时报Unknown database ‘springboot_db‘数据库不存在。检查application.yml中配置的数据库名。在 MySQL 中执行CREATE DATABASE语句创建数据库。访问localhost:8080报 Whitelabel Error Page没有定义根路径/的控制器。这是正常现象说明应用已启动但没映射/。访问具体的控制器路径如/user/list或创建首页控制器。访问localhost:8080/doc.html404Knife4j/Swagger 依赖未正确引入或配置错误。检查pom.xml中 knife4j 依赖检查application.yml配置。确保依赖和配置正确并尝试访问http://localhost:8080/swagger-ui.html或http://localhost:8080/v2/api-docs。插入中文到数据库变成乱码数据库字符集不支持或连接 URL 未指定字符集。检查数据库、表和字段的字符集是否为utf8mb4。确保 MySQL 配置和 JDBC URL 中的characterEncoding设置为utf-8或utf8mb4。调用接口返回404请求路径或方法错误。检查 Controller 的RequestMapping和方法上的GetMapping/PostMapping路径。使用 Knife4j 文档页面直接调试确保路径和方法匹配。MyBatis-Plus 逻辑删除失效实体类字段名与配置不一致或全局配置未生效。检查实体类deleted字段是否有TableLogic注解检查application.yml中logic-delete-field配置。确保注解和配置的字段名一致重启应用。Redis 缓存未生效Redis 配置错误或序列化问题导致存/取失败。检查 Redis 服务是否可连接检查RedisConfig配置类是否被加载。使用redis-cli手动测试连接在代码中打印redisTemplate操作的结果。10. 最佳实践与下一步建议通过以上步骤你已经完成了一个具备用户管理、缓存和接口文档的 SpringBoot 基础项目。以下是巩固学习和进一步探索的建议代码分层与规范严格遵守 Controller - Service - Mapper - Entity 的分层。Service 处理业务逻辑Controller 只负责参数校验和响应封装。异常统一处理使用ControllerAdvice或RestControllerAdvice编写全局异常处理器统一处理业务异常和系统异常返回友好的错误信息。参数校验在接收参数的 DTOData Transfer Object类上使用javax.validation注解如NotBlank,Email进行校验并在 Controller 方法参数前加Valid注解。使用 DTO 和 VO不要直接用 Entity 作为接口的请求和响应对象。创建独立的UserDTO用于接收请求和UserVO用于返回响应避免暴露不必要的字段或循环依赖。添加日志使用 SLF4J Logback 记录关键业务日志和错误日志便于排查问题。单元测试为 Service 层和 Controller 层编写 JUnit 单元测试确保核心逻辑正确。配置文件分离将application.yml拆分为application-dev.yml开发环境、application-prod.yml生产环境通过spring.profiles.active指定激活的环境。学习更多组件权限认证集成 Spring Security 或 Sa-Token实现基于角色的访问控制RBAC。接口文档深入学习 OpenAPI 3.0 规范使用Operation,Parameter等注解完善文档。数据库进阶学习 MyBatis-Plus 的分页插件、代码生成器、多数据源配置。缓存进阶学习 Redis 的多种数据结构、分布式锁、缓存雪崩/穿透/击穿解决方案。消息队列集成 RabbitMQ 或 Kafka实现异步和解耦。部署上线学习如何将 SpringBoot 项目打包成 Jar/War使用 Docker 容器化部署配合 Nginx 进行反向代理。这个项目是一个起点它帮你打通了 SpringBoot 开发的“任督二脉”。接下来你可以选择一个方向深入或者尝试用这套技术栈去实现一个更复杂的业务系统比如一个简单的博客系统或电商后台。记住动手编码和解决问题是最好的学习方式。建议收藏本文在实践过程中遇到问题时可以回头查阅对应的章节进行排查。