SpringBoot实战入门:3小时构建整合MyBatis-Plus与Redis的Web服务
这次我们来看一个面向初学者的 SpringBoot 快速入门学习路径。这个标题虽然带有“直男式教学”和“3小时搞定”的噱头,但核心指向一个非常实际的需求:如何高效、系统地掌握 SpringBoot 的核心开发能力。对于刚接触 Java 后端或从传统 SSM 框架转型的开发者来说,SpringBoot 的自动配置、内嵌服务器和“约定大于配置”的理念是巨大的生产力提升,但面对海量的教程和组件,如何抓住重点、快速搭建可运行的项目并理解其原理,是学习的关键。
本文不会空谈概念,而是聚焦于一套可落地的“最小可行学习方案”。我们将围绕一个典型的 SpringBoot 应用骨架,串联起项目创建、核心配置、数据访问、缓存集成、权限控制、接口文档生成等关键环节。目标是让你在理解核心流程的基础上,能独立完成一个具备基础 CRUD、缓存和认证功能的 Web 服务,并对接主流的 MySQL 和 Redis。整个过程强调动手实践,每个环节都提供可运行的代码示例和配置,帮你绕过初期最常见的配置坑。
1. 核心能力速览:SpringBoot 学习路径聚焦
在开始动手之前,我们先明确通过这条学习路径,你将掌握哪些具体能力,以及需要什么样的准备。
| 能力项 | 说明与目标 |
|---|---|
| 核心掌握 | 理解 SpringBoot 自动装配原理,掌握基于注解的开发模式,能独立创建和运行项目。 |
| 数据持久化 | 集成 MyBatis-Plus,完成从实体类、Mapper 到 Service 的完整数据层开发,实现基础 CRUD。 |
| 缓存集成 | 集成 Redis,实现缓存配置、数据存取及缓存注解(如@Cacheable)的使用。 |
| Web 开发 | 开发 RESTful API,处理请求参数、响应结果及全局异常。 |
| 权限认证 | 集成 Spring Security 或 Sa-Token,实现基于 Token 的接口权限控制。 |
| 接口文档 | 集成 Knife4j 或 SpringDoc,自动生成并在线调试 API 文档。 |
| 项目打包 | 使用 Maven 或 Gradle 将应用打包为可独立运行的 JAR 文件。 |
| 环境要求 | JDK 8+(推荐 JDK 11 或 17),Maven 3.6+或 Gradle,IDE(推荐 IntelliJ IDEA)。 |
| 辅助服务 | 需要本地或远程的MySQL 5.7+和Redis 5+服务。 |
| 学习特点 | 实战驱动,通过构建一个功能递进的项目来学习各组件,而非孤立看理论。 |
2. 适用场景与学习边界
这套学习方案主要适合以下人群:
- Java 后端初学者:希望快速上手一个现代、主流的 Java Web 框架。
- SSM/SSH 框架转型者:想了解 SpringBoot 如何简化传统配置。
- 需要快速原型验证的开发者:SpringBoot 能极快地搭建出可演示的后端服务。
- 求职面试准备者:SpringBoot 是 Java 后端岗位的必备技能,实战经验至关重要。
它能帮你解决:
- “从哪开始学”的迷茫:提供一条清晰、线性的实践路径。
- “配置太复杂”的困扰:基于 SpringBoot 的自动配置,大幅减少 XML 配置。
- “组件不会整合”的问题:演示如何将数据库、缓存、安全等常用组件有机组合。
需要注意的边界:
- 不是深度源码剖析:本文侧重于应用层快速上手,对 SpringBoot 启动流程、自动装配源码的深入分析需要另行学习。
- 不是微服务架构教程:不会涉及 Spring Cloud、服务注册发现、配置中心等微服务组件。
- 需要基础 Java 知识:假定你已掌握 Java 基础语法、面向对象概念以及基本的 SQL 知识。
- 关注合法合规:项目中使用的所有技术组件均为开源产品,请确保在学习和测试环境中使用。若用于生产,请遵循各自的开源协议。
3. 环境准备与前置检查
开始编码前,请确保你的开发环境已就绪。这是后续所有步骤的基础。
3.1 基础软件安装
JDK:确保已安装 JDK 8 或以上版本。推荐使用 JDK 11 或 17(LTS 版本)。在终端执行
java -version验证。java -version # 应输出类似:openjdk version "11.0.19" ...Maven:用于项目构建和依赖管理。安装后执行
mvn -v验证。mvn -v # 应输出 Apache Maven 版本信息建议配置国内镜像(如阿里云镜像)以加速依赖下载。修改
~/.m2/settings.xml文件。IDE:强烈推荐使用IntelliJ IDEA(社区版或旗舰版)。它对 SpringBoot 的支持最为完善,可以极大提升开发效率。
3.2 辅助服务安装与启动
我们的项目需要数据库和缓存,请提前准备好。
MySQL:
- 安装:从官网下载安装包或使用 Docker 快速启动。
- 验证:使用命令行或客户端(如 Navicat, MySQL Workbench)连接,确保服务运行。
- 创建数据库:我们后续会用到,先创建一个名为
springboot_demo的数据库。CREATE DATABASE IF NOT EXISTS `springboot_demo` DEFAULT CHARACTER SET utf8mb4;
Redis:
- 安装:Windows 用户可下载微软维护的版本或使用 WSL;Linux/macOS 用户可通过包管理器安装。
- 验证:启动 Redis 服务后,使用
redis-cli ping命令,收到PONG响应即表示成功。redis-cli ping # PONG
4. 项目创建与初始化
我们将使用 Spring Initializr 来生成项目骨架,这是最标准、最快捷的方式。
4.1 通过 IDEA 创建项目
- 打开 IntelliJ IDEA,选择
New Project。 - 左侧选择
Spring Initializr。 - 填写项目元数据:
- Project SDK:选择你安装的 JDK。
- Name:
demo(或你喜欢的项目名) - Location:选择项目存放路径。
- Type:
Maven - Language:
Java - Packaging:
Jar - Java Version:
11(与你安装的 JDK 版本匹配) - Group:
com.example - Artifact:
demo
- 点击
Next,进入依赖选择页面。在这里勾选我们初期需要的依赖:- Spring Web:用于构建 Web 应用,包含 RESTful API 支持。
- Lombok:简化 Java Bean 的编写(自动生成 getter/setter 等)。
- MySQL Driver:MySQL 数据库连接驱动。
- MyBatis Framework:数据持久层框架。(注意:这里我们先选 Spring 官方的 MyBatis Starter,后续会换成 MyBatis-Plus)
- 点击
Next,选择项目路径,然后Finish。IDEA 会自动下载初始依赖并打开项目。
4.2 调整依赖为 MyBatis-Plus
Spring Initializr 没有直接提供 MyBatis-Plus 的选项,我们需要手动修改pom.xml文件。
- 找到项目根目录下的
pom.xml。 - 移除之前选择的
MyBatis Framework依赖(如果已勾选),并添加 MyBatis-Plus 的 Starter 依赖。同时,我们提前把 Redis 和 Knife4j 的依赖也加上。<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- ... 其他父项目、groupId 等配置 ... --> <dependencies> <!-- Spring Boot Web Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- MySQL Driver --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- MyBatis-Plus Starter (替换官方的 mybatis-spring-boot-starter) --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> <!-- 请使用最新稳定版 --> </dependency> <!-- Redis Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- Knife4j 接口文档 (基于 Swagger 3) --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-spring-boot-starter</artifactId> <version>4.4.0</version> <!-- 请使用最新稳定版 --> </dependency> <!-- Spring Boot Test Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- ... 其他配置 ... --> </project> - 修改完成后,IDEA 通常会提示 Maven 依赖变更,点击刷新按钮(或右键
pom.xml->Maven->Reload project)下载新依赖。
5. 核心功能开发与验证
现在,我们从数据层到接口层,一步步构建功能。
5.1 数据库连接与实体类
配置数据库连接:打开
src/main/resources/application.properties文件,重命名为application.yml(YAML 格式更清晰),并配置:spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/springboot_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai username: root # 你的数据库用户名 password: 123456 # 你的数据库密码 redis: host: localhost port: 6379 # password: # 如果 Redis 设置了密码,取消注释并填写 database: 0 timeout: 3000ms lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0 # MyBatis-Plus 配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印 SQL 日志,便于调试 global-config: db-config: id-type: auto # 主键策略,数据库自增 logic-delete-field: deleted # 全局逻辑删除字段名(如果要用) logic-delete-value: 1 # 逻辑已删除值 logic-not-delete-value: 0 # 逻辑未删除值 # Knife4j 配置 knife4j: enable: true # 开启 Knife4j 增强 setting: language: zh_cn创建实体类:我们以一个简单的
User用户表为例。在src/main/java/com/example/demo/entity包下创建User.java。package com.example.demo.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.time.LocalDateTime; @Data // Lombok 注解,自动生成 getter, setter, toString 等 @TableName("sys_user") // 指定对应数据库表名 public class User { @TableId(type = IdType.AUTO) // 主键自增 private Long id; private String username; private String password; private String email; private Integer status; private LocalDateTime createTime; private LocalDateTime updateTime; }
5.2 MyBatis-Plus 数据层开发
MyBatis-Plus 提供了强大的 CRUD 接口,极大简化了开发。
创建 Mapper 接口:在
src/main/java/com/example/demo/mapper包下创建UserMapper.java。package com.example.demo.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.demo.entity.User; import org.apache.ibatis.annotations.Mapper; @Mapper // 标记为 MyBatis 的 Mapper,Spring 会自动扫描 public interface UserMapper extends BaseMapper<User> { // 继承 BaseMapper 后,基础的 CRUD 方法已全部拥有,无需编写 XML // 如果需要复杂查询,可以在此定义方法,并在 resources/mapper/ 下编写对应的 XML }创建 Service 层:在
src/main/java/com/example/demo/service包下创建UserService.java接口及其实现。// UserService.java (接口) package com.example.demo.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.demo.entity.User; public interface UserService extends IService<User> { // 可以在此定义业务相关的方法 User getUserByUsername(String username); }// UserServiceImpl.java (实现类) package com.example.demo.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.demo.entity.User; import com.example.demo.mapper.UserMapper; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Override public User getUserByUsername(String username) { LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getUsername, username); return this.getOne(wrapper); } }
5.3 控制器与 RESTful API
现在创建 Controller 来暴露 HTTP 接口。
在src/main/java/com/example/demo/controller包下创建UserController.java。
package com.example.demo.controller; import com.example.demo.entity.User; import com.example.demo.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/user") @Tag(name = "用户管理", description = "用户相关接口") // Knife4j 接口分组 public class UserController { @Autowired private UserService userService; @GetMapping("/{id}") @Operation(summary = "根据ID查询用户") // 接口描述 public User getUserById(@PathVariable Long id) { return userService.getById(id); } @GetMapping("/list") @Operation(summary = "获取用户列表") public List<User> getUserList() { return userService.list(); } @PostMapping @Operation(summary = "新增用户") public Boolean addUser(@RequestBody User user) { // 实际业务中,密码需要加密,此处仅为演示 return userService.save(user); } @PutMapping @Operation(summary = "更新用户") public Boolean updateUser(@RequestBody User user) { return userService.updateById(user); } @DeleteMapping("/{id}") @Operation(summary = "删除用户") public Boolean deleteUser(@PathVariable Long id) { return userService.removeById(id); } }5.4 集成 Redis 缓存
Spring Data Redis 提供了简单的模板和注解式缓存。
配置 Redis 序列化(可选但推荐):为了在 Redis 中看到更可读的数据,可以配置 Key 和 Value 的序列化方式。创建一个配置类
RedisConfig.java。package com.example.demo.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 RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 设置 key 的序列化器 template.setKeySerializer(new StringRedisSerializer()); // 设置 value 的序列化器为 JSON template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.afterPropertiesSet(); return template; } }使用缓存注解:修改
UserService的实现,为getUserByUsername方法添加缓存。// 在 UserServiceImpl.java 中修改 getUserByUsername 方法 @Override @Cacheable(value = "user", key = "#username", unless = "#result == null") // 缓存名为user,key为用户名,如果结果为null则不缓存 public User getUserByUsername(String username) { System.out.println("从数据库查询用户: " + username); // 模拟缓存未命中时打印 LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getUsername, username); return this.getOne(wrapper); }并在启动类
DemoApplication上添加@EnableCaching注解以开启缓存功能。@SpringBootApplication @EnableCaching // 开启缓存注解支持 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
5.5 集成 Knife4j 生成接口文档
Knife4j 的配置非常简单,我们之前已经在application.yml中开启了增强。现在需要创建一个配置类来设定文档信息。
在config包下创建SwaggerConfig.java(或OpenApiConfig.java)。
package com.example.demo.config; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SwaggerConfig { @Bean public OpenAPI springShopOpenAPI() { return new OpenAPI() .info(new Info() .title("SpringBoot 实战项目 API 文档") .description("这是一个整合了 MyBatis-Plus、Redis 的 SpringBoot 演示项目") .version("v1.0.0")); } }6. 功能测试与效果验证
现在,启动项目并逐一验证我们开发的功能。
6.1 启动项目与数据库表创建
- 启动主类:运行
src/main/java/com/example/demo/DemoApplication.java中的main方法。控制台应看到 SpringBoot 的 Banner 和启动日志,没有报错。 - 自动建表:MyBatis-Plus 本身不提供 DDL 自动生成。为了快速测试,我们可以使用其代码生成器或在
resources下放置一个schema.sql文件让 Spring Boot 启动时执行。这里我们手动执行 SQL 创建表:USE springboot_demo; CREATE TABLE IF NOT EXISTS `sys_user` ( `id` bigint NOT NULL AUTO_INCREMENT, `username` varchar(50) DEFAULT NULL, `password` varchar(100) DEFAULT NULL, `email` varchar(100) DEFAULT NULL, `status` int DEFAULT '1', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
6.2 接口测试与缓存验证
访问接口文档:项目启动后,打开浏览器,访问
http://localhost:8080/doc.html。你将看到 Knife4j 漂亮的接口文档页面,里面列出了我们编写的所有用户管理接口。- 验证点:能正常打开文档页面,且
UserController下的接口清晰可见。
- 验证点:能正常打开文档页面,且
测试新增用户接口:
- 在 Knife4j 页面找到
POST /api/user接口,点击“调试”。 - 在请求体中输入 JSON:
{ "username": "testUser", "password": "123456", "email": "test@example.com" } - 点击“发送”,观察响应。应为
true。 - 验证点:接口返回成功,并去数据库查询
sys_user表,确认数据已插入。
- 在 Knife4j 页面找到
测试查询用户列表接口:
- 调试
GET /api/user/list接口。 - 验证点:返回包含刚才新增用户的 JSON 数组。
- 调试
测试 Redis 缓存:
- 调试
GET /api/user/{id}接口,传入刚才新增用户的 ID。 - 第一次调用时,控制台会打印“从数据库查询用户...”的 SQL 日志。
- 立即再次调用同一个接口。如果缓存生效,控制台将不会再次打印 SQL 日志,且响应速度会更快。
- 你还可以使用
redis-cli命令行工具,执行keys *查看是否有user::testUser这样的键,验证数据是否已存入 Redis。 - 验证点:第二次及后续查询不再访问数据库,证明
@Cacheable注解生效。
- 调试
6.3 项目打包与运行
使用 Maven 打包:在项目根目录下执行命令。
mvn clean package -DskipTests命令执行成功后,会在
target目录下生成demo-0.0.1-SNAPSHOT.jar文件。运行 JAR 包:
java -jar target/demo-0.0.1-SNAPSHOT.jar验证点:应用应能正常启动,访问
http://localhost:8080/doc.html接口文档依然可用。这证明我们成功构建了一个可独立部署的 SpringBoot 应用。
7. 常见问题与排查方法
在学习和实践过程中,你可能会遇到以下问题。这里提供排查思路。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
启动时报java.net.ConnectException: Connection refused | 数据库或 Redis 服务未启动。 | 1. 检查 MySQL 服务状态。 2. 检查 Redis 服务状态。 3. 确认 application.yml中的连接地址、端口、密码是否正确。 | 启动相应的服务,或修正配置文件。 |
启动时报Failed to configure a DataSource | 未配置数据源,或数据库驱动依赖缺失。 | 1. 检查pom.xml是否有mysql-connector-j依赖。2. 检查 application.yml中spring.datasource配置是否正确。 | 添加依赖,或正确配置数据源。如果暂时不用数据库,可在启动类排除数据源自动配置:@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) |
访问接口返回404 | 1. 请求路径错误。 2. Controller 未被扫描到。 | 1. 核对浏览器地址或 Knife4j 中的接口路径。 2. 确认 Controller 类在启动类所在包或其子包下。 | 修正请求路径。或将启动类移动到更顶层的包。 |
| MyBatis-Plus 打印的 SQL 中表名不对 | 实体类未使用@TableName指定表名,或数据库表不存在。 | 1. 检查实体类上的@TableName注解。2. 检查数据库是否存在该表。 | 添加或修正@TableName注解。执行建表 SQL。 |
@Cacheable缓存不生效 | 1. 启动类未加@EnableCaching。2. Redis 连接失败。 3. 方法被内部调用(非代理调用)。 | 1. 检查启动类注解。 2. 检查 Redis 配置和连接。 3. 确保缓存方法是通过 Spring 代理对象调用的(如从 Controller 调用 Service)。 | 添加注解,检查 Redis,确保调用方式正确。 |
Knife4j 页面doc.html无法访问 | 1. 依赖未正确引入。 2. 路径被拦截。 3. 项目未启动成功。 | 1. 检查pom.xml中 knife4j 依赖。2. 检查是否有安全框架(如 Security)拦截了静态资源。 3. 查看启动日志是否有错误。 | 确认依赖,调整安全配置,或直接访问http://localhost:8080/v3/api-docs看原始 JSON 是否存在。 |
打包后运行报No main manifest attribute | Maven 打包插件配置问题,未指定主类。 | 检查pom.xml中的spring-boot-maven-plugin插件。 | 确保使用了 Spring Boot 的父工程或正确配置了该插件。 |
8. 最佳实践与进阶方向
完成基础功能搭建后,这里有一些建议帮助你走得更远。
- 代码分层清晰:坚持
Controller->Service->Mapper的分层结构,各司其职。Controller只负责参数校验和响应封装,业务逻辑放在Service层。 - 使用统一响应体:定义如
Result<T>这样的通用响应类,包含code、msg、data字段,使前端对接更规范。 - 全局异常处理:使用
@ControllerAdvice和@ExceptionHandler捕获并处理全局异常,返回友好的错误信息,而不是堆栈轨迹。 - 参数校验:在接收参数的 DTO 类上使用
javax.validation注解(如@NotBlank,@Email)进行校验,并在 Controller 方法参数前加@Valid注解触发校验。 - 配置文件分离:将
application.yml按环境拆分,如application-dev.yml(开发)、application-prod.yml(生产),通过spring.profiles.active指定激活的环境。 - 连接池监控:生产环境建议使用 Druid 连接池替代默认的 HikariCP,因为它提供了更强大的监控功能。
- 安全与权限:引入
Spring Security或更轻量的Sa-Token进行完整的认证授权管理,而不仅仅是简单的 Token 校验。 - 单元测试:为 Service 层和 Controller 层编写单元测试(使用
@SpringBootTest),保证代码质量。 - API 版本管理:如果 API 需要迭代,考虑在 URL 路径(如
/api/v1/user)或请求头中管理版本号。 - 部署与监控:学习使用 Docker 容器化部署 SpringBoot 应用,并集成 Actuator 端点进行健康检查和指标监控。
这条学习路径的核心价值在于,它通过一个连贯的项目,将 SpringBoot 及其核心生态组件(Web、MyBatis-Plus、Redis、接口文档)串联起来,让你在动手实践中理解它们是如何协同工作的。先跑通这个“最小可行系统”,再根据实际需求,去深入每个组件的细节和高级特性,这样的学习效率最高,也最能建立信心。建议你将这个项目作为基础模板保存,后续的新项目或新功能都可以在此基础上快速扩展。
