Spring Boot 全方位指南:从项目初始化到分层架构搭建
Spring Boot 全方位指南:从项目初始化到分层架构搭建
本教程旨在引导 Java 开发者,特别是 Spring Boot 的初学者,从零开始创建一个结构清晰、功能完备的后端项目。
我们将从项目初始化开始,详细讲解每一项依赖的作用,然后配置数据库,并最终搭建起经典的 MVC(Model-View-Controller)分层架构。
1. 依赖讲解
在创建项目之前,理解核心依赖的作用至关重要。它们是构建项目的基础。
通用依赖
- Spring Web: 这是构建 Web 应用的核心模块,包括传统的 Spring MVC 和 RESTful API。它内置了 Tomcat 服务器,使我们无需额外配置 Web 服务器就能运行项目。
- Lombok: 一个非常实用的 Java 库,可以通过注解自动生成构造函数、Getter/Setter、
toString()
等模板代码,极大地简化了实体类和数据传输对象的编写。 - Spring Boot DevTools: 开发阶段的辅助工具。它提供了热部署功能,当你修改代码后,应用会自动重新启动,无需手动操作,从而显著提升开发效率。
- Springdoc OpenAPI: 用于根据代码自动生成 OpenAPI 3.0 格式的 API 文档。它与 Swagger UI 集成,提供了一个美观且可交互的 API 测试界面。
数据库相关依赖
根据你选择的数据库,需要引入不同的依赖:
- MongoDB:
- Spring Data MongoDB: 提供了在 Spring 应用中与 MongoDB 数据库交互的便捷支持,包括对象-文档映射 (ODM) 和 Repository 抽象。
- MySQL:
- Spring Data JPA: Java Persistence API (JPA) 是 Java EE 的标准规范,用于对象关系映射 (ORM)。Spring Data JPA 在其基础上提供了更高层次的抽象,简化了数据访问层的开发。
- MySQL Driver: 这是 MySQL 数据库的 JDBC 驱动,是 Java 应用连接 MySQL 数据库的桥梁。
2. 初始化项目步骤详细
我们将使用 Spring Initializr 这个官方工具来生成项目骨架。
请按照以下步骤进行配置:
-
Project: 选择 Maven。Maven 是一个强大的项目管理和构建工具。
-
Language: 选择 Java。
-
Spring Boot: 选择一个稳定且被广泛推荐的版本,例如
3.5.3
或其他3.x.x
系列的非快照版本。 -
Project Metadata:
Group
:com.example
(通常是你的公司或组织域名倒写)Artifact
:my-spring-project
(项目名称)Name
:my-spring-project
(同上)Description
:Demo project for Spring Boot
(项目描述)Package name
:com.example.myspringproject
(项目的基础包名)
-
Packaging: 选择 Jar。这是现代微服务架构中最常见的打包方式,项目会作为一个独立的可执行文件运行。
-
Java: 选择一个长期支持 (LTS) 版本,如 17 或 21。
-
Dependencies: 在页面右侧,点击 “ADD DEPENDENCIES…” 按钮,然后搜索并添加以下依赖:
- Spring Web
- Lombok
- Spring Boot DevTools
- 根据你的数据库选择:
- MongoDB 用户: 添加
Spring Data MongoDB
。 - MySQL 用户: 添加
Spring Data JPA
和MySQL Driver
。
- MongoDB 用户: 添加
完成以上配置后,点击 “GENERATE” 按钮下载项目压缩包,然后在你的 IDE (如 IntelliJ IDEA 或 Eclipse 或 VS Code) 中导入该 Maven 项目。
附录:在 Visual Studio Code 中打开和运行项目
对于 VS Code 用户,请遵循以下步骤来设置和运行你的 Spring Boot 项目。
-
安装必备扩展:
在开始之前,请确保你已经在 VS Code 中安装了 Java 开发的必备扩展。在扩展市场中搜索并安装以下扩展包,它提供了对 Java 开发的全面支持:Extension Pack for Java
(来自 Microsoft)
-
打开项目:
将从 Spring Initializr 下载的压缩包解压。然后,在 VS Code 中,通过菜单栏的文件 (File)
>打开文件夹... (Open Folder...)
,选择刚刚解压的项目根目录。 -
项目加载:
VS Code 会自动识别这是一个基于 Maven 的 Java 项目。右下角会弹出提示,询问你是否信任此工作区,请选择“是”。之后,Java 扩展会自动开始下载项目所需的依赖项 (Dependencies)。你可以在左侧边栏的JAVA PROJECTS
视图中看到项目的结构和依赖加载进度。 -
运行项目:
项目依赖加载完毕后,请在文件资源管理器中找到src/main/java/com/example/myspringproject/MySpringProjectApplication.java
文件。你有多种方式启动它:- 在编辑器中运行: 打开该文件。你会发现在
main
方法的上方,VS Code 会显示Run | Debug
的可点击选项。同时,编辑器的右上角也会出现一个播放 (▶️) 按钮。点击其中任意一个都可以启动应用。 - 在文件浏览器中运行: 在左侧的文件资源管理器中,直接右键点击
MySpringProjectApplication.java
文件,在弹出的上下文菜单中选择运行 Java (Run Java)
。
- 在编辑器中运行: 打开该文件。你会发现在
3. 项目转化为基于 Java 8 的修改方法(按需)
虽然推荐使用 Java 17 或 21,但如果你因旧有环境限制必须使用 Java 8,可以手动修改 pom.xml
文件。
打开项目根目录下的 pom.xml
文件,找到 <properties>
标签,将其中的 <java.version>
修改为 1.8
。
<properties><java.version>1.8</java.version>
</properties>
同时,你需要确保你的 Spring Boot 版本与 Java 8 兼容。Spring Boot 3.x 及以上版本要求 Java 17 或更高,因此你需要选择一个 2.x.x
的版本,例如 2.7.18
。这通常在 <parent>
标签中修改:
<!-- pom.xml -->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version><relativePath/>
</parent>
重要:jakarta
vs javax
命名空间变更
这是一个非常关键的技术点。从 Spring Boot 3.0 开始,Spring 框架迁移到了 Jakarta EE 9 规范,最直观的变化就是 Java EE API 的包名从 javax.*
变成了 jakarta.*
。
- Spring Boot 3.x (Java 17+): 使用
jakarta.persistence.*
- Spring Boot 2.x (Java 8/11): 使用
javax.persistence.*
因此,如果你按照本节步骤降级到了 Spring Boot 2.x,在后续编写 JPA 实体类(如 User
实体)时,必须手动将所有 import jakarta.persistence.*
修改为 import javax.persistence.*
,否则项目将无法编译。
4. 需要手动添加的依赖
Springdoc OpenAPI
并非总是在所有 Spring Initializr 版本中都作为默认选项提供。如果初始化时未能添加,你需要手动将其添加到 pom.xml
的 <dependencies>
区域。
重要提示: springdoc-openapi
的版本与 Spring Boot 的版本是紧密相关的。请根据你的 Spring Boot 版本选择正确的依赖。
场景一:Spring Boot 3.x (推荐)
如果你使用的是 Spring Boot 3.x (例如 3.5.3
),你需要添加 v2.x.x
版本的 springdoc-openapi
。
<!-- pom.xml -->
<dependencies><!-- ... 其他依赖 ... --><!-- Springdoc OpenAPI for Spring Boot 3 --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.5.0</version></dependency>
</dependencies>
注意: 请检查并使用最新的
2.x
稳定版本号。
场景二:Spring Boot 2.x (兼容旧版 Java 8)
如果你根据前面的步骤降级到了 Spring Boot 2.x (例如 2.7.18
),则必须使用 v1.x.x
版本的 springdoc-openapi
,并且 artifactId
也不同。
<!-- pom.xml -->
<dependencies><!-- ... 其他依赖 ... --><!-- Springdoc OpenAPI for Spring Boot 2 --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>1.8.0</version></dependency>
</dependencies>
注意: 请检查并使用最新的
1.x
稳定版本号。
5. 数据库支持
接下来,我们将在 src/main/resources/
目录下的配置文件中添加数据库连接信息。你可以选择 application.properties
或 application.yml
格式。yml
格式层级更清晰,是目前更主流的选择。
情况一:集成 MongoDB
MongoDB 的 Windows 下安装方法可见 这篇文章
确保你的 pom.xml
文件中包含 spring-boot-starter-data-mongodb
依赖。
application.properties
格式配置:
# MongoDB Configuration
# 使用 URI 方式连接,包含了地址、端口、数据库名等信息
spring.data.mongodb.uri=mongodb://localhost:27017/mydatabase
# 如果你的 MongoDB 设置了用户名和密码,可以使用以下格式
# spring.data.mongodb.uri=mongodb://user:password@localhost:27017/mydatabase# 或者分别指定主机、端口和数据库名
# spring.data.mongodb.host=localhost
# spring.data.mongodb.port=27017
# spring.data.mongodb.database=mydatabase
# spring.data.mongodb.username=your_username
# spring.data.mongodb.password=your_password
# spring.data.mongodb.authentication-database=admin # 指定认证数据库
application.yml
格式配置:
spring:data:mongodb:uri: mongodb://localhost:27017/mydatabase# 或者分别指定主机、端口和数据库名# host: localhost# port: 27017# database: mydatabase# username: your_username# password: your_password# authentication-database: admin # 指定认证数据库
authentication-database
配置详解
authentication-database
是一个非常重要的配置项,尤其是在需要认证的生产环境中。
- 作用: 它用于指定对哪个数据库进行用户身份验证。当你提供的
username
和password
不是在当前连接的数据库 (mydatabase
) 中创建的,而是在另一个特定的数据库(通常是admin
库)中创建时,就必须设置此项。- 常见场景: 在 MongoDB 中,管理员通常会在
admin
数据库中创建用户,并授予该用户访问其他一个或多个数据库的权限。在这种情况下,即使你的应用程序操作的是mydatabase
,认证过程也必须在admin
数据库中进行。- 如何配置: 如果你使用独立的配置项(而非 URI),请添加
spring.data.mongodb.authentication-database=admin
。如果使用 URI,可以在连接字符串中添加authSource
参数,例如:mongodb://user:password@localhost:27017/mydatabase?authSource=admin
。
情况二:集成 MySQL
确保你的 pom.xml
文件中包含 spring-boot-starter-data-jpa
和 mysql-connector-j
依赖。
application.properties
格式配置:
# MySQL Datasource Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=your_password# JPA (Hibernate) Configuration
# ddl-auto:
# none: 不做任何操作
# validate: 校验 schema,如果实体与表结构不匹配则报错
# update: 启动时更新 schema,使其与实体匹配
# create: 每次启动时都删除并重新创建 schema
# create-drop: 启动时创建,关闭时删除
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true # 在控制台打印执行的 SQL 语句,方便调试
application.yml
格式配置:
spring:datasource:url: jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: rootpassword: your_passwordjpa:hibernate:ddl-auto: updateshow-sql: true
6. 修改服务端口号
Spring Boot 内嵌的 Web 服务器(如 Tomcat)默认使用 8080
端口。如果该端口被占用或你希望使用其他端口,可以通过修改配置文件轻松实现。此项配置与数据库配置一样,都位于 src/main/resources/
目录下。
application.properties
格式配置:
# Server Configuration
server.port=8090
application.yml
格式配置:
server:port: 8090
提示: 修改端口后,所有访问地址(包括 API 文档地址)都需要使用新的端口号,例如
http://localhost:8090/swagger-ui.html
。
7. 搭建基础分层结构
现在,我们开始搭建项目的核心代码结构。一个良好的分层结构可以使代码更清晰、更易于维护。我们遵循 Entity -> Repository -> Service -> Controller 的经典模式。
首先,在 src/main/java/com/example/myspringproject/
目录下创建以下四个包:
entity
(或model
): 存放数据实体类。repository
: 存放数据访问接口。service
: 存放业务逻辑代码。controller
: 存放 API 接口。
在 VS Code 中创建包 (文件夹):
- 在左侧的
文件夹 (FOLDERS)
视图中,找到并展开src/main/java/com/example/myspringproject
目录。- 右键点击
myspringproject
文件夹。- 在弹出的菜单中选择
新建文件夹 (New Folder)
。- 输入第一个包名,例如
entity
,然后按 Enter。- 重复以上步骤,创建
repository
、service
和controller
这三个包。
创建实体层 (Entity/Model)
实体是与数据库表或文档结构对应的 Java 对象。
MongoDB 场景:
创建一个 User
类,使用 @Document
注解表示它对应 MongoDB 中的一个集合。
src/main/java/com/example/myspringproject/entity/User.java
package com.example.myspringproject.entity;import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;@Data // Lombok 注解,自动生成 Getter, Setter, toString() 等方法
@Document(collection = "users") // 映射到 MongoDB 中的 "users" 集合
public class User {@Idprivate String id; // MongoDB 的主键通常是字符串类型private String username;private String email;
}
MySQL 场景:
创建一个 User
类,使用 @Entity
注解表示它是一个 JPA 实体。
src/main/java/com/example/myspringproject/entity/User.java
package com.example.myspringproject.entity;// 重要提示:
// 如果你使用的是 Spring Boot 2.x (对应 Java 8),
// 需要将下面的 'jakarta.persistence' 全部替换为 'javax.persistence'
import jakarta.persistence.*;
import lombok.Data;@Data // Lombok 注解
@Entity // 声明这是一个 JPA 实体
@Table(name = "users") // 映射到数据库中的 "users" 表
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增策略private Long id; // MySQL 的主键通常是 Long 类型private String username;private String email;
}
创建数据访问层 (Repository)
Repository 层负责与数据库进行直接交互,提供基础的增删改查功能。
MongoDB 场景:
创建一个 UserRepository
接口,继承 MongoRepository
。
src/main/java/com/example/myspringproject/repository/UserRepository.java
package com.example.myspringproject.repository;import com.example.myspringproject.entity.User;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;@Repository
public interface UserRepository extends MongoRepository<User, String> {// Spring Data MongoDB 会自动实现基础的 CRUD 方法// 你也可以在这里定义符合规范的自定义查询方法,例如:// Optional<User> findByUsername(String username);
}
MySQL 场景:
创建一个 UserRepository
接口,继承 JpaRepository
。
src/main/java/com/example/myspringproject/repository/UserRepository.java
package com.example.myspringproject.repository;import com.example.myspringproject.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;@Repository // 声明这是一个 Spring 管理的 Bean
public interface UserRepository extends JpaRepository<User, Long> {// JpaRepository 已经提供了丰富的 CRUD 操作// 和分页、排序等功能。
}
创建业务逻辑层 (Service)
Service 层封装了核心的业务逻辑,它调用 Repository 层来持久化数据。
Service 的代码对于 MongoDB 和 MySQL 几乎一样,唯一区别在于 findUserById
方法的参数类型,这取决于 User
实体的主键类型 (String
for MongoDB, Long
for MySQL)。
下面以 MongoDB 为例展示 UserService
的代码。对于 MySQL,只需将 findUserById
方法的参数 id
类型从 String
改为 Long
即可。
src/main/java/com/example/myspringproject/service/UserService.java
package com.example.myspringproject.service;import com.example.myspringproject.entity.User;
import com.example.myspringproject.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service // 声明这是一个业务逻辑组件
public class UserService {private final UserRepository userRepository;// 推荐使用构造函数注入,确保依赖的不可变性@Autowiredpublic UserService(UserRepository userRepository) {this.userRepository = userRepository;}/*** 创建一个新用户* @param user 用户实体* @return 保存后的用户实体*/public User createUser(User user) {return userRepository.save(user);}/*** 根据 ID 查找用户* @param id 用户 ID (MongoDB 使用 String, MySQL 使用 Long)* @return 用户实体,如果不存在则返回 null*/public User findUserById(String id) { // MySQL 用户请将 String id 改为 Long idreturn userRepository.findById(id).orElse(null);}
}
创建表现层 (Controller)
Controller 层负责接收 HTTP 请求,调用 Service 层处理业务,并返回 HTTP 响应。
Controller 的代码在 MongoDB 和 MySQL 两种场景下几乎完全相同。唯一的区别在于 getUserById
方法中 ID 的类型。
下面以 MongoDB 场景为例,其中用户 ID 为 String
类型。如果你使用 MySQL,只需将 getUserById
方法的参数 @PathVariable String id
修改为 @PathVariable Long id
即可,其他部分完全相同
src/main/java/com/example/myspringproject/controller/UserController.java
package com.example.myspringproject.controller;import com.example.myspringproject.entity.User;
import com.example.myspringproject.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;@RestController // 结合了 @Controller 和 @ResponseBody,返回 JSON 数据
@RequestMapping("/api/users") // 定义此控制器下所有 API 的基础路径
public class UserController {private final UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}/*** 创建用户的 API 端点* @param user 从请求体中接收的 User 对象* @return 创建的用户信息*/@PostMappingpublic User createUser(@RequestBody User user) {return userService.createUser(user);}/*** 根据 ID 查询用户的 API 端点* @param id 从路径中获取的用户 ID (String)* @return 包含用户信息的 ResponseEntity*/@GetMapping("/{id}")public ResponseEntity<User> getUserById(@PathVariable String id) {User user = userService.findUserById(id);if (user != null) {return ResponseEntity.ok(user); // 返回 200 OK 和用户信息} else {return ResponseEntity.notFound().build(); // 返回 404 Not Found}}
}
8. 生成并访问 API 文档
现在,你的项目已经准备就绪。
-
运行项目:
- 在 IDE 中,找到主应用程序类(
MySpringProjectApplication.java
),右键点击并选择 “Run”。 - 或者在项目根目录下打开终端,执行命令
mvn spring-boot:run
。
- 在 IDE 中,找到主应用程序类(
-
访问 API 文档:
- 项目成功启动后,打开浏览器并访问:
http://localhost:8080/swagger-ui.html
- 你将看到一个由 Springdoc 生成的交互式 API 页面。
- 项目成功启动后,打开浏览器并访问:
-
测试 API:
- 在 Swagger UI 页面,你可以看到
POST /api/users
和GET /api/users/{id}
两个端点。 - 展开
POST
端点,点击 “Try it out”,在请求体中输入 JSON 数据(如{"username": "Alice", "email": "alice@example.com"}
),然后点击 “Execute”。 - 复制响应中返回的 ID,然后使用
GET
端点进行查询。
- 在 Swagger UI 页面,你可以看到
至此,你已经成功地创建了一个结构完整、包含数据库集成和 API 文档的 Spring Boot 后端项目。以此为基础,你可以继续扩展更复杂的业务功能。