Spring Boot 实战入门:从零构建 CRUD Web 应用与 RESTful API

Spring Boot 应该怎么学?如果你觉得它概念多、配置杂、上手慢,那这篇文章就是为你准备的。我们不谈空泛的理论,直接聚焦于“能不能用”和“怎么用”。Spring Boot 的核心价值在于,它能让你用最少的配置,快速构建出独立运行、生产就绪的 Spring 应用。对于 Java 开发者,尤其是刚接触企业级开发或想从传统 Spring MVC 项目转型的同学来说,掌握 Spring Boot 意味着开发效率的质变。

这篇文章将采用一种直击要害的方式,带你快速上手 Spring Boot。我们会重点关注几个实际开发中最关心的问题:环境门槛高不高?启动一个项目到底需要几步?如何集成 MyBatis、MySQL 这些必备组件?怎么处理 Web 请求和前后端交互?以及最终如何打包部署。整个过程会围绕一个具体的实战项目展开,你将看到从零到一构建一个具备基础 CRUD 和 API 接口的 Web 应用的全过程。无论你是想快速完成课程设计、毕业设计,还是为面试积累实战经验,这篇内容都能提供一条清晰的路径。

1. 核心能力速览

在深入细节之前,我们先快速了解 Spring Boot 能为你做什么,以及它的核心特点。

能力项说明与价值
项目类型用于快速构建独立、生产级的 Spring 应用框架。
核心主张“约定大于配置”,极大简化了传统 Spring 繁琐的 XML 和 Java 配置。
内嵌服务器默认集成 Tomcat、Jetty 或 Undertow,应用可打包为可直接运行的 JAR 文件,无需单独部署 WAR 到外部服务器。
自动配置根据项目依赖(如 spring-boot-starter-web, spring-boot-starter-data-jpa)自动配置 Spring 应用上下文和第三方库。
起步依赖提供一系列spring-boot-starter-*依赖,一站式引入某技术栈所需的所有库及其兼容版本。
生产就绪特性内置健康检查、指标监控、外部化配置等功能,开箱即用。
环境门槛仅需 JDK 8+ 和 Maven/Gradle 构建工具,对硬件无特殊要求,普通开发机即可运行。
启动方式通过main方法直接运行,或使用java -jar命令启动打包后的 JAR 文件。
适合场景微服务、RESTful API、全栈 Web 应用、批处理作业、集成测试等。特别适合需要快速原型开发和迭代的项目。

2. 适用场景与使用边界

Spring Boot 并非万能,明确其适用边界能帮助你更好地决策。

它非常适合以下场景:

  1. 快速原型与验证:当你有一个新想法需要快速验证时,Spring Boot 能让你在几分钟内搭建起一个可运行的后端服务。
  2. 微服务架构:每个微服务都是独立的、轻量级的 JAR,Spring Boot 是构建微服务的理想选择。
  3. 传统企业应用现代化:将老旧的、配置复杂的 Spring 项目迁移到 Spring Boot,能显著简化部署和运维。
  4. 学生与初学者:对于学习 Java Web 开发的同学,Spring Boot 绕开了大量环境配置和整合的坑,让你更专注于业务逻辑和核心概念。
  5. 需要内嵌容器的应用:开发需要独立交付、不依赖外部应用服务器的工具或应用。

它可能不是最佳选择,或需要额外考虑的场景:

  1. 极度轻量级的任务:如果只是写一个简单的脚本或工具,引入完整的 Spring Boot 框架可能显得臃肿。
  2. 已有复杂 XML 配置的大型遗留项目:直接迁移到 Spring Boot 的改造成本可能很高,需要评估。
  3. 对启动速度有极端要求的应用:虽然 Spring Boot 2.x 以后启动速度已大幅优化,但与原生编译(如 Spring Native)或更轻量的框架相比仍有差距。
  4. 需要深度定制 Servlet 容器:虽然可以定制,但 Spring Boot 的强项在于“开箱即用”,过度定制可能违背其设计初衷。

安全与合规边界:

  • 依赖安全:定期检查并升级spring-boot-starter-parent或依赖版本,以获取安全补丁。
  • 配置安全:切勿将数据库密码、API密钥等敏感信息硬编码在代码或application.properties中。应使用环境变量、配置服务器或加密方式管理。
  • API 暴露:生产环境务必关闭不必要的 Actuator 端点(如/env,/heapdump),或为其配置严格的访问控制。

3. 环境准备与前置条件

开始之前,确保你的开发环境已经就绪。这个过程非常简单。

  1. Java 开发工具包:Spring Boot 3.x 需要JDK 17或更高版本;Spring Boot 2.x 需要JDK 8或更高版本。建议使用 JDK 17 或 21 以获得更好的性能和长期支持。在终端输入java -version验证。
  2. 构建工具MavenGradle。本文以 Maven 为例,因为它与 Spring Boot 的集成更广泛。在终端输入mvn -v验证。
  3. 集成开发环境IntelliJ IDEA(社区版或旗舰版)或Eclipse。IDEA 对 Spring Boot 的支持更为出色,能提供强大的代码提示、运行和调试功能。
  4. 数据库:按需准备。例如学习常用MySQL,可下载安装 MySQL Community Server,或使用 Docker 运行。也可以使用内存数据库如H2进行快速测试,无需安装。
  5. 其他工具Git(版本控制)、Postmancurl(API 测试)、浏览器。

验证环境:打开命令行,依次执行以下命令,确认输出正常。

java -version # 应输出类似:openjdk version "17.0.10" 2024-01-16 mvn -v # 应输出 Apache Maven 版本信息,如 3.9.6

4. 创建第一个 Spring Boot 项目

我们将使用 Spring Initializr,这是官方推荐的、最快捷的项目生成方式。

4.1 通过 IDEA 创建(推荐)

  1. 打开 IntelliJ IDEA,选择New Project
  2. 在左侧选择Spring Initializr
  3. Project SDK选择你安装的 JDK 17 或更高版本。
  4. Spring Initializr服务 URL 处使用默认地址即可。
  5. 填写项目元数据:
    • Group:com.example(通常为公司域名倒写)
    • Artifact:demo(项目名称)
    • Name:demo
    • Package name:com.example.demo
    • Packaging:Jar(默认)
    • Java Version:17(与你安装的 JDK 版本对应)
  6. 点击Next,进入依赖选择页面。这是关键步骤,我们为第一个项目添加:
    • Spring Web: 用于构建 Web 应用,包含 RESTful API 支持。
    • Spring Boot DevTools: 开发工具,支持热加载,提升开发效率。
    • Lombok: 通过注解简化 Java Bean 的编写(如 getter/setter)。
    • (可选)MySQL Driver: 如果你打算连接 MySQL。
    • (可选)Spring Data JPA: 用于数据库操作。
  7. 点击Next,选择项目存储位置,然后点击Finish

IDEA 会自动下载项目模板并构建,完成后你会看到一个标准的 Spring Boot 项目结构。

4.2 通过网站创建

访问 start.spring.io ,在网页上填写与上述类似的项目信息、选择依赖,然后点击Generate下载一个 ZIP 压缩包,解压后用 IDEA 打开即可。

4.3 项目结构解析

生成的项目结构如下:

demo ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ └── demo │ │ │ └── DemoApplication.java // 主启动类 │ │ └── resources │ │ ├── application.properties // 配置文件 │ │ └── static // 静态资源 (HTML, CSS, JS) │ │ └── templates // 模板文件 (Thymeleaf, Freemarker) │ └── test // 测试代码 └── pom.xml // Maven 依赖管理文件

核心文件说明:

  • DemoApplication.java: 包含main方法的启动类。@SpringBootApplication注解是关键。
  • application.properties: 应用配置文件,可以配置服务器端口、数据库连接等。
  • pom.xml: 管理项目依赖。Spring Boot 父项目 (spring-boot-starter-parent) 统一管理了大量依赖的版本。

5. 编写第一个 RESTful API

现在,让我们创建一个简单的接口,验证项目是否能跑通。

  1. 创建 Controller:在com.example.demo包下新建一个类HelloController.java
    package com.example.demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController // 声明这是一个 REST 控制器,返回值直接写入 HTTP 响应体 public class HelloController { @GetMapping("/hello") // 处理 GET 请求,路径为 /hello public String sayHello(@RequestParam(value = "name", defaultValue = "World") String name) { return String.format("Hello, %s! This is Spring Boot.", name); } }
  2. 启动应用:找到DemoApplication.java,右键点击,选择Run ‘DemoApplication’。IDEA 会启动内嵌的 Tomcat 服务器。
  3. 测试接口:观察控制台日志,看到类似Tomcat started on port(s): 8080的信息后,打开浏览器或使用 Postman。
    • 访问:http://localhost:8080/hello
    • 返回:Hello, World! This is Spring Boot.
    • 带参数访问:http://localhost:8080/hello?name=Spring
    • 返回:Hello, Spring! This is Spring Boot.

恭喜!你的第一个 Spring Boot 应用已经成功运行并对外提供了 API 服务。整个过程没有配置任何 XML,没有部署 WAR 包,仅仅写了几行代码。

6. 连接数据库与数据操作

一个完整的应用离不开数据持久化。我们以 MySQL 和 Spring Data JPA 为例,演示如何集成数据库。

6.1 添加依赖与配置

  1. 修改pom.xml:如果你创建项目时未选择 MySQL 和 JPA 依赖,需要手动添加。
    <!-- 在 <dependencies> 节点内添加 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> <!-- 运行时才需要 --> </dependency>
  2. 配置数据库连接:打开src/main/resources/application.properties文件,添加配置。
    # 服务器端口 server.port=8080 # 数据库连接配置 spring.datasource.url=jdbc:mysql://localhost:3306/springboot_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=your_password # 替换为你的数据库密码 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # JPA 配置 spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect spring.jpa.hibernate.ddl-auto=update # 启动时根据实体类自动更新表结构(仅用于开发) spring.jpa.show-sql=true # 在控制台显示执行的 SQL 语句,方便调试
    注意:请先在 MySQL 中创建名为springboot_demo的数据库。

6.2 创建实体类与 Repository

  1. 创建实体类:对应数据库中的表。新建entity包和User.java类。
    package com.example.demo.entity; import jakarta.persistence.*; import lombok.Data; @Data // Lombok 注解,自动生成 getter, setter, toString 等方法 @Entity // 标明这是一个 JPA 实体类 @Table(name = "user") // 指定对应的表名,默认为类名小写 public class User { @Id // 主键 @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增 private Long id; @Column(nullable = false, unique = true) // 对应列,非空且唯一 private String username; @Column(nullable = false) private String password; private String email; }
  2. 创建 Repository 接口:用于数据访问。新建repository包和UserRepository.java接口。
    package com.example.demo.repository; import com.example.demo.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository // 可省略,Spring 会自动识别 public interface UserRepository extends JpaRepository<User, Long> { // 无需实现任何方法,JpaRepository 已提供了基础的 CRUD 方法 // 可以根据方法名自动推导查询,例如: User findByUsername(String username); }
    JpaRepository<User, Long>提供了save(),findById(),findAll(),deleteById()等常用方法。

6.3 创建 Service 与 Controller

  1. 创建 Service 层:处理业务逻辑。新建service包和UserService.java
    package com.example.demo.service; import com.example.demo.entity.User; import com.example.demo.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class UserService { @Autowired private UserRepository userRepository; public User saveUser(User user) { // 简单的保存逻辑,实际项目需增加校验、加密等 return userRepository.save(user); } public List<User> getAllUsers() { return userRepository.findAll(); } public Optional<User> getUserById(Long id) { return userRepository.findById(id); } public void deleteUser(Long id) { userRepository.deleteById(id); } }
  2. 完善 Controller:新建或修改UserController.java来暴露 REST API。
    package com.example.demo.controller; import com.example.demo.entity.User; import com.example.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Optional; @RestController @RequestMapping("/api/users") // 所有接口前缀为 /api/users public class UserController { @Autowired private UserService userService; @PostMapping // POST /api/users public User createUser(@RequestBody User user) { return userService.saveUser(user); } @GetMapping // GET /api/users public List<User> getAllUsers() { return userService.getAllUsers(); } @GetMapping("/{id}") // GET /api/users/1 public Optional<User> getUserById(@PathVariable Long id) { return userService.getUserById(id); } @DeleteMapping("/{id}") // DELETE /api/users/1 public String deleteUser(@PathVariable Long id) { userService.deleteUser(id); return "User deleted successfully."; } }

6.4 测试数据库操作

  1. 重启应用:由于修改了配置和代码,需要重启DemoApplication
  2. 观察日志:启动时,Hibernate 会根据ddl-auto=update自动在springboot_demo数据库中创建user表。你可以在控制台看到create table user ...的 SQL 语句。
  3. 使用 Postman 测试 API
    • POSThttp://localhost:8080/api/users
      • Body (raw JSON):{"username": "testUser", "password": "123456", "email": "test@example.com"}
      • 应返回创建成功的用户信息(包含生成的 id)。
    • GEThttp://localhost:8080/api/users
      • 应返回包含刚才创建用户的列表。
    • GEThttp://localhost:8080/api/users/1
      • 应返回 id 为 1 的用户信息。
    • DELETEhttp://localhost:8080/api/users/1
      • 应返回删除成功的消息,再次 GET 列表应为空。

至此,一个具备完整 CRUD 功能的 Spring Boot 后端服务已经搭建完成。

7. 集成 Thymeleaf 实现简单页面

虽然前后端分离是主流,但了解如何渲染页面也有其价值。我们使用 Thymeleaf 模板引擎快速实现一个页面。

  1. 添加依赖:在pom.xml中添加 Thymeleaf 起步依赖。
    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
  2. 创建页面控制器:新建PageController.java
    package com.example.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller // 注意这里是 @Controller,不是 @RestController public class PageController { @GetMapping("/") public String index(Model model) { model.addAttribute("message", "Welcome to Spring Boot with Thymeleaf!"); model.addAttribute("users", List.of("Alice", "Bob", "Charlie")); // 模拟数据 return "index"; // 对应 src/main/resources/templates/index.html } }
  3. 创建 HTML 模板:在src/main/resources/templates/目录下新建index.html
    <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Spring Boot Demo</title> </head> <body> <h1 th:text="${message}">Default Message</h1> <ul> <li th:each="user : ${users}" th:text="${user}">User Name</li> </ul> <p>Current Time: <span th:text="${#temporals.format(#temporals.createNow(), 'yyyy-MM-dd HH:mm:ss')}">2024-01-01 00:00:00</span></p> </body> </html>
  4. 访问页面:重启应用,访问http://localhost:8080/,你将看到一个渲染了动态数据的 HTML 页面。

8. 配置文件与多环境

Spring Boot 支持灵活的配置管理,这是生产就绪的重要特性。

  1. 配置文件优先级:Spring Boot 会按以下顺序加载配置,后加载的覆盖先加载的。
    • 项目根目录/config子目录下的application.properties
    • 项目根目录下的application.properties
    • classpath:/config/下的application.properties
    • classpath:/下的application.properties(即resources目录下)
  2. 多环境配置:可以创建application-{profile}.properties文件来区分环境。
    • application-dev.properties: 开发环境配置(如连接本地数据库)。
    • application-prod.properties: 生产环境配置(如连接线上数据库)。
    • application.properties中通过spring.profiles.active=dev来激活指定环境的配置。
  3. YAML 格式:除了.properties,还可以使用更清晰的.yml.yaml格式。
    # application.yml 示例 server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/demo username: root password: secret jpa: hibernate: ddl-auto: update show-sql: true custom: api: key: my-secret-key # 自定义配置
  4. 读取自定义配置:使用@Value注解或@ConfigurationProperties
    @Component public class MyConfig { @Value("${custom.api.key}") private String apiKey; // 或者使用类型安全的绑定 @ConfigurationProperties(prefix = "custom.api") @Data public static class ApiProperties { private String key; } }

9. 打包与部署

开发完成后,我们需要将应用打包并部署到服务器或容器中。

9.1 打包为可执行 JAR

Spring Boot 的 Maven 插件使得打包极其简单。

  1. 执行打包命令:在项目根目录(pom.xml所在目录)打开终端,执行:
    mvn clean package
  2. 找到 JAR 包:命令执行成功后,在target/目录下会生成一个demo-0.0.1-SNAPSHOT.jar文件(名称取决于你的pom.xml中的artifactIdversion)。这个 JAR 包是可执行的,因为它内嵌了 Tomcat 服务器和所有依赖。
  3. 运行 JAR 包
    java -jar target/demo-0.0.1-SNAPSHOT.jar
    应用会以与在 IDEA 中相同的方式启动。你可以通过--server.port=8081参数来覆盖配置文件中的端口。

9.2 使用 Docker 部署(可选)

Docker 能提供一致的环境。首先在项目根目录创建Dockerfile

# 使用官方 Eclipse Temurin 17 JDK 镜像作为基础镜像 FROM eclipse-temurin:17-jre-alpine # 维护者信息 LABEL maintainer="your-email@example.com" # 在容器内创建一个应用目录 WORKDIR /app # 将构建好的 JAR 文件复制到容器内 COPY target/demo-0.0.1-SNAPSHOT.jar app.jar # 暴露应用运行的端口 EXPOSE 8080 # 指定容器启动时执行的命令 ENTRYPOINT ["java", "-jar", "app.jar"]

然后构建镜像并运行容器:

# 1. 确保已打包好 JAR 文件 (mvn clean package) # 2. 构建 Docker 镜像 docker build -t springboot-demo . # 3. 运行容器,将宿主机的 8080 端口映射到容器的 8080 端口 docker run -d -p 8080:8080 --name demo-app springboot-demo

访问http://localhost:8080即可访问容器中运行的应用。

10. 常见问题与排查方法

在学习和使用 Spring Boot 的过程中,你可能会遇到以下常见问题。

问题现象可能原因排查方式解决方案
启动失败,端口被占用默认端口 8080 被其他程序占用。查看日志Port 8080 was already in use.1. 在application.properties中修改server.port
2. 关闭占用端口的进程。
无法连接到数据库数据库配置错误、服务未启动、网络不通。查看启动日志中的数据库连接错误信息。1. 检查spring.datasource.url,username,password
2. 确认 MySQL 服务已启动。
3. 检查防火墙和网络。
JPA 实体类扫描不到主启动类@SpringBootApplication所在的包层级不对。实体类或 Repository 不在主类子包下。1. 将实体类、Repository 等放在主类所在包或其子包下。
2. 使用@EntityScan@EnableJpaRepositories注解手动指定扫描路径。
依赖下载失败或冲突Maven 仓库网络问题,或依赖版本冲突。查看 IDEA 的 Maven 面板或执行mvn dependency:tree1. 检查网络,更换 Maven 镜像源。
2. 使用mvn dependency:tree分析依赖树,排除冲突依赖。
热部署不生效未正确配置或 IDEA 未开启自动编译。检查是否添加了spring-boot-devtools依赖。1. 确认依赖已添加。
2. IDEA 中:Settings -> Build -> Compiler,勾选Build project automatically
3.Ctrl+Shift+Alt+/,选择Registry,勾选compiler.automake.allow.when.app.running
打包后运行找不到主类打包插件配置问题或主类路径错误。检查pom.xmlspring-boot-maven-plugin配置。确保pom.xml中使用了正确的打包插件:
xml <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
@Autowired 注入失败被注入的类未被 Spring 管理(缺少注解),或存在多个同类型 Bean。查看启动日志中的 Bean 创建和依赖注入错误。1. 确保被注入的类上有@Component,@Service,@Repository等注解。
2. 使用@Qualifier指定 Bean 名称。
跨域请求被阻止前端应用(如 Vue 运行在localhost:3000)访问后端 API 时触发浏览器同源策略。浏览器控制台出现 CORS 错误。在后端配置全局 CORS 规则:
java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:3000") .allowedMethods("*"); } }

11. 最佳实践与进阶方向

掌握了基础之后,遵循一些最佳实践能让你的项目更健壮、更易维护。

  1. 分层架构:严格遵守 Controller -> Service -> Repository 的分层,每层职责单一。Controller 只负责参数校验和响应封装,Service 处理业务逻辑,Repository 负责数据访问。
  2. 统一响应封装:设计一个通用的响应类(如Result<T>),包含状态码、消息和数据,让所有 API 返回格式统一。
  3. 全局异常处理:使用@ControllerAdvice@ExceptionHandler捕获并处理各类异常,返回友好的错误信息,而不是暴露堆栈跟踪。
  4. 参数校验:在接收参数的 DTO 类字段上使用@NotNull,@Size,@Email等注解,并在 Controller 方法参数前加@Valid注解进行自动校验。
  5. 使用日志框架:使用 SLF4J 配合 Logback 或 Log4j2 记录日志,合理使用不同级别(DEBUG, INFO, WARN, ERROR),便于问题排查。
  6. 配置文件分离:将敏感信息(密码、密钥)从application.properties中移出,使用环境变量或配置中心管理。
  7. 编写单元测试:为 Service 层和 Controller 层编写单元测试(使用 JUnit 和 Mockito)和集成测试,保证代码质量。

下一步可以探索的进阶主题:

  • Spring Security: 为你的应用添加认证和授权功能。
  • Spring Cloud: 如果你开始构建微服务,Spring Cloud 提供了服务发现、配置中心、网关等全套解决方案。
  • Redis 缓存: 集成 Redis 提升应用性能。
  • 消息队列: 集成 RabbitMQ 或 Kafka 进行异步处理和解耦。
  • 定时任务: 使用@Scheduled注解执行定时任务。
  • API 文档: 集成 Swagger/OpenAPI 自动生成 API 文档。
  • 监控与度量: 使用 Spring Boot Actuator 暴露应用健康指标,并集成 Prometheus 和 Grafana。

Spring Boot 的学习曲线前期非常平缓,能让你快速获得成就感。它的价值在于通过“约定大于配置”的理念,将开发者从繁琐的配置中解放出来,更专注于业务创新。从创建一个能响应的“Hello World”接口,到构建一个包含数据库操作、页面渲染、并最终能打包部署的完整应用,整个过程在几个小时内就能走通。关键在于动手实践,遇到问题多查阅官方文档和社区。当你熟悉了这套范式,开发效率的提升将是实实在在的。