Spring Boot 工程开发全流程说明
1. 文档目的
本文以一个典型的 Maven + Spring Boot 后端工程为对象,完整说明项目从创建、依赖下载、代码编译、应用启动、配置加载、Bean 创建、依赖注入、数据库与 Redis 连接,到接收 HTTP 请求、执行业务逻辑、打包和部署的全过程。
本文重点回答以下问题:
- Maven、Spring Boot、JVM 和 IntelliJ IDEA 分别负责什么;
pom.xml、Starter、驱动和 Jar 包之间是什么关系;- Spring Boot 为什么以
main方法作为启动入口; SpringApplication.run()启动后做了什么;application.yml是什么时候读取的;- Controller、Service、Mapper 和配置类是如何变成 Bean 的;
- 数据库和 Redis 是如何自动连接的;
- GET、POST 请求是如何进入 Controller 的;
- 一个完整 Spring Boot 项目是如何编译、运行和部署的。
2. Spring Boot 工程中的核心参与者
一个典型的 Spring Boot 工程不是由单一工具完成的,而是由多个部分协同工作。
2.1 IntelliJ IDEA
IntelliJ IDEA 是开发工具,主要负责:
- 编辑 Java 代码;
- 显示项目目录;
- 提供代码提示;
- 调用 Maven;
- 调用 Java 编译器;
- 启动 JVM;
- 调试 Spring Boot 程序;
- 显示运行日志。
IDEA 本身不是 Spring Boot,也不是 Maven。它只是将这些工具集成到图形界面中。
例如,在 IDEA 中右键 pom.xml,选择:
text
Add as Maven Project
含义是:
告诉 IDEA,这个
pom.xml是 Maven 项目的构建描述文件,请使用 Maven 管理该项目。
IDEA 随后会调用 Maven 解析依赖、模块、插件和构建配置。
2.2 Maven
Maven 是项目构建和依赖管理工具。
它主要负责:
- 读取
pom.xml; - 下载项目所需的 Jar 包;
- 管理依赖版本;
- 编译 Java 代码;
- 执行测试;
- 复制资源文件;
- 将项目打包成 Jar 或 War;
- 管理多模块项目。
POM 是 Maven 的项目对象模型,默认文件名为 pom.xml。Maven 在执行命令时,默认从当前工作目录寻找 pom.xml。Maven 还约定了 src/main/java、src/main/resources、src/test/java 和 target 等标准目录。
2.3 JVM
JVM 是 Java 虚拟机,负责真正执行编译后的 Java 字节码。
JVM 主要负责:
- 加载
.class文件; - 查找并调用
main方法; - 创建 Java 对象;
- 执行 Java 方法;
- 管理内存;
- 执行垃圾回收;
- 加载 classpath 中的 Jar 包。
Spring Boot 最终仍然是一个 Java 程序,因此必须运行在 JVM 中。
2.4 Spring Framework
Spring Framework 提供:
- IoC 容器;
- Bean 管理;
- 依赖注入;
- Spring MVC;
- 事务管理;
- 数据访问;
- AOP;
- 事件机制等。
Spring IoC 容器负责实例化、配置和组装 Bean。Bean 本质上仍然是普通 Java 对象,只是它的创建和依赖关系由 Spring 容器管理。
2.5 Spring Boot
Spring Boot 建立在 Spring Framework 之上,主要解决 Spring 项目配置复杂的问题。
Spring Boot 提供:
- 自动配置;
- Starter 依赖;
- 外部化配置;
- 内嵌 Web 服务器;
- 可执行 Jar;
- 统一启动入口;
- 默认项目约定;
- 生产运行支持。
Spring Boot 的自动配置会根据 classpath 中存在的 Jar 依赖、项目配置和已经存在的 Bean,判断需要自动创建哪些组件。
因此,Spring Boot 更准确地说是:
一个高度集成、约定优于配置并支持自动配置的 Spring 应用开发框架。
它不只是代码生成脚手架。
3. 一个典型的项目结构
一个基础 Spring Boot Maven 工程可能具有以下结构:
text
demo-project/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/demo/
│ │ │ ├── DemoApplication.java
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ ├── mapper/
│ │ │ ├── domain/
│ │ │ └── config/
│ │ └── resources/
│ │ ├── application.yml
│ │ ├── application-dev.yml
│ │ └── mapper/
│ └── test/
│ └── java/
└── target/
各目录的作用如下。
text
pom.xml
定义项目坐标、依赖、插件、模块和构建规则。
text
src/main/java
保存业务 Java 源代码。
text
src/main/resources
保存 YAML、Properties、Mapper XML、静态资源等。
text
src/test/java
保存测试代码。
text
target
保存 Maven 编译和打包结果。
4. 项目创建阶段
Spring Boot 项目可以通过多种方式创建。
常见方式包括:
- Spring Initializr;
- IDEA 的 Spring Boot 项目向导;
- 现有项目模板;
- 企业脚手架;
- 手动创建 Maven 项目。
创建项目时,一般需要选择:
text
项目类型:Maven
开发语言:Java
Spring Boot 版本
JDK 版本
groupId
artifactId
依赖模块
例如:
text
groupId: org.example
artifactId: demo-system
会形成 Maven 项目坐标:
xml
<groupId>org.example</groupId>
<artifactId>demo-system</artifactId>
<version>1.0.0</version>
5. pom.xml 与 Maven 依赖加载流程
5.1 pom.xml 是什么
pom.xml 是 Maven 项目的核心描述文件。
一个简化示例如下:
xml
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>指定版本</version>
</parent>
<groupId>org.example</groupId>
<artifactId>demo-system</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
</dependencies>
</project>
5.2 Maven 如何识别 pom.xml
命令行执行:
bash
mvn clean package
Maven 默认检查当前工作目录:
text
当前目录/pom.xml
例如当前目录为:
text
E:\program\demo-system
Maven 默认读取:
text
E:\program\demo-system\pom.xml
也可以显式指定:
bash
mvn -f E:\program\demo-system\pom.xml clean package
5.3 IDEA 中的 Maven 识别
在 IDEA 中执行:
text
右键 pom.xml
→ Add as Maven Project
是在告诉 IDEA:
将这个 POM 注册为 Maven 项目的构建入口。
之后 IDEA 会:
text
读取 pom.xml
↓
调用 Maven
↓
解析 dependencies
↓
下载缺少的 Jar
↓
加入项目 classpath
↓
建立 Maven 模块结构
这一操作只影响 IDEA 对项目的管理。
命令行 Maven 不依赖 IDEA 的这个操作。
5.4 Maven 从哪里下载依赖
Maven 仓库分为本地仓库和远程仓库。
典型过程如下:
text
Maven 读取 dependency
↓
检查本地仓库
↓
本地不存在
↓
访问远程仓库
↓
下载 POM 和 Jar
↓
保存到本地仓库
Windows 默认本地仓库通常位于:
text
C:\Users\用户名\.m2\repository
例如 MySQL 驱动可能被保存在:
text
.m2/repository/com/mysql/mysql-connector-j/
5.5 什么是 classpath
Classpath 可以理解为:
JVM 和 Java 编译器寻找 Java 类的路径集合。
例如程序需要:
java
org.springframework.boot.SpringApplication
JVM 会在 classpath 中寻找包含这个类的 Jar。
如果 Maven 已经下载并加入 Spring Boot Jar:
text
能够找到 SpringApplication
如果没有相关依赖:
text
找不到 SpringApplication
编译失败或运行失败
6. Starter、驱动和客户端
6.1 Starter 是什么
Starter 是一组相关依赖的集合,也是 Spring Boot 自动配置体系的常用入口。
例如:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
表示项目需要 Web 开发能力。
它会传递引入相关组件,例如:
text
Spring MVC
JSON 处理
日志
内嵌 Web 服务器
基础自动配置
Spring Boot 官方将 Starter 作为面向具体功能的依赖集合,例如 Web、JDBC、Redis、安全、消息等。
Starter 可以理解为:
text
功能套餐
6.2 数据库驱动是什么
数据库驱动负责 Java 程序和具体数据库之间的底层通信。
例如 MySQL 驱动:
xml
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
它负责:
- 识别
jdbc:mysql:地址; - 建立网络连接;
- 账号认证;
- 发送 SQL;
- 接收数据库返回结果;
- 将结果转换成 JDBC 对象。
数据库 Starter 和数据库驱动的分工是:
text
JDBC/MyBatis Starter
→ 负责 Spring 集成、自动配置和上层管理
MySQL Driver
→ 负责与 MySQL 真正通信
6.3 Redis 客户端是什么
Redis 通常不使用 JDBC 驱动,而是使用 Redis Java 客户端,例如:
- Lettuce;
- Jedis;
- Redisson。
Spring Data Redis 使用 RedisConnectionFactory 对底层 Redis 客户端进行抽象,并提供 RedisTemplate 等上层操作工具。
例如:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
该 Starter 默认可集成具体 Redis 客户端,并提供 Spring Data Redis 的操作能力。
7. Maven 构建阶段
在 Spring Boot 启动之前,Maven 通常已经完成依赖解析和项目编译。
正确顺序是:
text
读取 pom.xml
↓
下载 Starter、驱动和其他 Jar
↓
建立 classpath
↓
编译 Java 源代码
↓
复制资源文件
↓
执行测试
↓
打包
↓
运行 Spring Boot
Maven 使用构建生命周期组织编译、测试、打包和安装等阶段。常见生命周期命令包括 clean、compile、test、package 和 install。
例如:
bash
mvn clean package
含义是:
text
clean
→ 删除上一次构建结果
package
→ 编译、测试并生成 Jar 或 War
需要特别注意:
不是先执行
SpringApplication.run(),再让 Maven 下载依赖。
而是 Maven 先准备好依赖和代码,JVM 才能运行 Spring Boot。
8. Spring Boot 启动类
一个典型启动类如下:
java
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
也可以写成:
java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication application =
new SpringApplication(DemoApplication.class);
application.run(args);
}
}
两种写法本质一致。
8.1 为什么这个类可以执行
定义一个类本身不会自动执行。
例如:
java
public class DemoApplication {
}
只表示定义了一个类。
当类中存在:
java
public static void main(String[] args)
并且 JVM 被要求以这个类作为主类启动时,JVM 会调用:
java
DemoApplication.main(args);
因此,真正的入口是:
java
public static void main(String[] args)
而不是类名本身。
8.2 为什么 main 不需要创建对象
因为 main 是静态方法:
java
public static void main(String[] args)
static 表示方法属于类本身,可以通过类名调用。
JVM 不需要先执行:
java
new DemoApplication();
而是可以直接调用:
java
DemoApplication.main(args);
8.3 DemoApplication.class 是什么
下面的表达式:
java
DemoApplication.class
不是创建 DemoApplication 对象,也不是再次执行该类。
它是获取这个类对应的 Class 类型信息。
Spring Boot 将这个类作为主要配置源。SpringApplication 的构造参数通常是配置类或组件类。
Spring Boot 可以通过它读取:
- 类名;
- 包名;
- 注解;
- 方法;
- 配置声明。
9. @SpringBootApplication 的作用
java
@SpringBootApplication
public class DemoApplication {
}
@SpringBootApplication 是 Spring Boot 的组合注解。
可以近似理解为包含:
java
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
它主要提供三项能力。
9.1 配置入口
当前类被视为 Spring Boot 的主要配置入口。
9.2 自动配置
Spring Boot 根据:
- classpath 中有哪些 Jar;
- YAML 中有哪些配置;
- 当前已经有哪些 Bean;
- 当前应用类型是什么;
判断需要自动创建哪些组件。
Spring Boot 自动配置会基于项目加入的 Jar 依赖尝试配置应用,并允许开发者通过自定义 Bean 逐步替换默认配置。
9.3 组件扫描
Spring 会从启动类所在包开始扫描候选组件。
假设启动类位于:
java
package org.example;
默认扫描范围是:
text
org.example
org.example.controller
org.example.service
org.example.mapper
org.example.config
以及更深层的子包
Spring 的 classpath 扫描会发现满足条件的组件类,并为它们注册 Bean 定义。
因此,启动类通常应该放在项目的根包位置。
10. SpringApplication.run() 的启动流程
执行:
java
SpringApplication.run(DemoApplication.class, args);
以后,Spring Boot 会进入运行阶段。
可以将其概括为:
text
准备启动环境
↓
读取外部配置
↓
判断应用类型
↓
创建 ApplicationContext
↓
加载自动配置
↓
扫描组件
↓
注册 BeanDefinition
↓
创建 Bean
↓
完成依赖注入
↓
执行初始化逻辑
↓
启动内嵌 Web 服务器
↓
注册接口映射
↓
应用进入运行状态
10.1 创建 Environment
Spring Boot 会创建环境对象:
java
Environment
Environment 用于统一保存配置属性,例如:
text
server.port = 8080
spring.datasource.url = jdbc:mysql://localhost:3306/demo
spring.data.redis.host = localhost
10.2 读取配置来源
Spring Boot 支持将配置放在:
- Properties 文件;
- YAML 文件;
- 环境变量;
- Java 系统属性;
- 命令行参数;
- 外部配置文件等。
外部化配置使同一套应用代码可以在不同环境中使用不同参数。
10.3 创建 Spring 容器
Spring Boot 创建:
java
ApplicationContext
它就是主要的 Spring IoC 容器。
ApplicationContext 负责:
- 注册 Bean;
- 创建 Bean;
- 配置 Bean;
- 组装 Bean;
- 管理 Bean 生命周期;
- 提供事件机制;
- 提供资源和环境访问。
Spring 官方将 ApplicationContext 描述为负责实例化、配置和组装 Bean 的 IoC 容器。
10.4 自动配置
Spring Boot 会检查 classpath 中的依赖。
概念上类似:
text
有 Spring MVC
→ 配置 Web MVC
有 JDBC
→ 尝试配置 DataSource
有 MyBatis
→ 配置 SqlSessionFactory 和 Mapper
有 Redis
→ 配置 RedisConnectionFactory 和 RedisTemplate
有 Security
→ 配置安全过滤链
自动配置一般是有条件的,不是无条件执行。
例如:
text
classpath 中存在某个类
配置属性存在
容器中还没有对应 Bean
条件满足时,自动配置才会生效。
11. 配置文件加载流程
11.1 默认配置文件
Spring Boot 常用配置文件包括:
text
application.properties
application.yml
application.yaml
通常放在:
text
src/main/resources
例如:
yaml
server:
port: 8080
spring:
application:
name: demo-system
YAML 会被展开为属性:
text
server.port = 8080
spring.application.name = demo-system
11.2 多环境配置
项目可能包含:
text
application.yml
application-dev.yml
application-test.yml
application-prod.yml
基础配置:
yaml
spring:
profiles:
active: dev
表示激活:
text
dev
最终会加载:
text
application.yml
+
application-dev.yml
Spring Profiles 用于隔离不同环境下的配置或组件。
11.3 配置如何进入 Java 对象
使用 @Value
java
@Value("${server.port}")
private int port;
使用 Environment
java
private final Environment environment;
public TestService(Environment environment) {
this.environment = environment;
}
public void printPort() {
String port = environment.getProperty("server.port");
}
使用 @ConfigurationProperties
YAML:
yaml
demo:
name: converter-system
timeout: 30
Java:
java
@Component
@ConfigurationProperties(prefix = "demo")
public class DemoProperties {
private String name;
private Integer timeout;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
}
Spring Boot 支持通过 @Value、Environment 和 @ConfigurationProperties 使用外部配置。
12. Bean、IoC 和依赖注入
12.1 什么是 Bean
Bean 是由 Spring 容器创建和管理的对象。
例如:
java
@Service
public class UserService {
}
UserService 是类。
Spring 创建的:
java
UserService对象
才是 Bean。
准确关系是:
text
Java 类
↓ Spring 实例化
Java 对象
↓ 注册到容器
Spring Bean
12.2 哪些类会成为 Bean
常见组件注解包括:
java
@Component
@Service
@Repository
@Controller
@RestController
@Configuration
例如:
java
@Service
public class UserService {
}
java
@RestController
public class UserController {
}
这些类位于扫描范围内时,Spring 会注册对应 Bean。
普通类:
java
public class NormalObject {
}
没有被扫描或显式注册时,不会自动成为 Bean。
12.3 @Configuration 和 @Bean
配置类:
java
@Configuration
public class AppConfig {
@Bean
public MyClient myClient() {
return new MyClient();
}
}
这里有两个层次:
text
AppConfig
→ 配置类本身由 Spring 管理
myClient()
→ 方法返回值注册为 Bean
因此:
java
@Bean
表示将该方法返回的对象交给 Spring 容器管理。
12.4 依赖注入
例如:
java
@Service
public class UserService {
}
Controller 依赖它:
java
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
}
Spring 启动时近似完成:
java
UserService userService = new UserService();
UserController userController =
new UserController(userService);
但这些操作由 Spring 容器自动完成。
这就是依赖注入。
推荐使用构造器注入,因为依赖关系清晰,也便于测试。
12.5 IoC 的含义
传统方式由开发者控制对象创建:
java
UserService userService = new UserService();
Spring 方式由容器负责对象创建:
text
开发者声明需要什么
↓
Spring 创建对象
↓
Spring 注入对象
对象创建控制权从业务代码转移给 Spring 容器,因此称为:
text
控制反转 IoC
13. 数据库连接全流程
13.1 引入依赖
基础 JDBC 示例:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
也可能使用:
text
MyBatis Starter
MyBatis-Plus Starter
JPA Starter
dynamic-datasource Starter
但底层仍然需要相应数据库驱动。
13.2 配置连接参数
yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
这些配置提供:
- 数据库类型;
- 服务器地址;
- 端口;
- 数据库名;
- 用户名;
- 密码。
Java 的 DataSource 是管理数据库连接的标准接口,通常使用 URL 和认证信息建立数据库连接。
13.3 自动配置过程
text
Spring Boot 启动
↓
发现 JDBC 或数据访问依赖
↓
发现数据库驱动
↓
读取 spring.datasource 配置
↓
创建 DataSource
↓
创建连接池
↓
注册为 Bean
Spring Boot 常通过连接池管理数据库连接。
其内部过程可近似理解为:
java
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(
"jdbc:mysql://localhost:3306/demo"
);
dataSource.setUsername("root");
dataSource.setPassword("123456");
真实代码由自动配置和连接池组件完成。
13.4 数据库服务必须已经存在
Spring Boot 不会自动安装 MySQL,也不会自动创建完整业务数据库。
运行前通常需要保证:
text
MySQL 服务已启动
数据库已创建
账号存在
密码正确
端口可访问
数据库表已初始化
否则可能出现:
text
Connection refused
Communications link failure
Access denied
Unknown database
13.5 Mapper 使用 DataSource
以 MyBatis 为例:
java
@Mapper
public interface UserMapper {
User selectById(Long id);
}
Service:
java
@Service
public class UserService {
private final UserMapper userMapper;
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User getById(Long id) {
return userMapper.selectById(id);
}
}
执行链路是:
text
Service
↓
Mapper
↓
MyBatis
↓
DataSource
↓
数据库连接池
↓
数据库
14. Redis 连接全流程
14.1 引入依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
如果项目使用 Redisson,也可能引入第三方 Redisson Starter。
14.2 配置 Redis
yaml
spring:
data:
redis:
host: localhost
port: 6379
password: 123456
database: 0
timeout: 10s
14.3 自动配置过程
text
Spring Boot 启动
↓
发现 Redis Starter
↓
发现 Lettuce、Jedis 或其他客户端
↓
读取 Redis 配置
↓
创建 RedisConnectionFactory
↓
创建 RedisTemplate 或 StringRedisTemplate
↓
注册为 Bean
Spring Data Redis 提供 Redis 连接和 Repository 支持,并通过连接工厂抽象底层客户端。
14.4 使用 Redis Bean
java
@Service
public class CacheService {
private final StringRedisTemplate redisTemplate;
public CacheService(
StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void save(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
}
这里没有手动:
java
new StringRedisTemplate();
因为该对象已经由 Spring Boot 自动配置并注册为 Bean。
14.5 Redis 服务也必须存在
Spring Boot 不会因为存在 YAML 就自动安装 Redis。
必须确保:
text
Redis 服务已启动
host 正确
port 正确
password 正确
网络可访问
15. Spring MVC 和 HTTP 请求监听
15.1 引入 Web Starter
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Spring Boot 可以使用内嵌 Web 服务器创建自包含 HTTP 应用。
15.2 启动 Web 服务器
SpringApplication.run() 执行过程中会启动内嵌服务器。
常见服务器包括:
- Tomcat;
- Jetty;
- Undertow;
- 响应式应用中的 Netty。
启动完成后,服务器持续监听配置端口,例如:
yaml
server:
port: 8080
表示监听:
text
8080
15.3 定义 Controller
java
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return "用户:" + id;
}
@PostMapping
public String createUser() {
return "创建成功";
}
}
Spring 启动时会建立映射:
text
GET /users/{id}
→ getUser()
POST /users
→ createUser()
15.4 DispatcherServlet
在 Spring MVC 中,DispatcherServlet 是前端控制器。
它负责接收 Web 请求,然后将请求交给已注册的处理器。Spring MVC 使用前端控制器模式,DispatcherServlet 提供统一请求处理流程,而映射、参数处理和异常处理等工作由相关组件完成。
请求过程如下:
text
浏览器或前端
↓
HTTP 请求
↓
内嵌 Web 服务器
↓
过滤器链
↓
DispatcherServlet
↓
HandlerMapping
↓
Controller 方法
↓
Service
↓
Mapper / Redis
↓
返回结果
↓
JSON 序列化
↓
HTTP 响应
16. 分层架构中的调用关系
一个常见后端分层结构是:
text
Controller
↓
Service
↓
Mapper / Repository
↓
Database
16.1 Controller 层
负责:
- 接收请求;
- 获取参数;
- 参数校验;
- 调用 Service;
- 返回结果。
不建议在 Controller 中直接编写复杂业务逻辑。
16.2 Service 层
负责:
- 核心业务规则;
- 多步骤业务流程;
- 事务控制;
- 调用 Mapper;
- 调用 Redis;
- 调用其他外部服务。
16.3 Mapper 或 Repository 层
负责:
- SQL 查询;
- 数据新增;
- 数据修改;
- 数据删除;
- 实体与数据库记录转换。
16.4 Domain、Entity、DTO 和 VO
常见对象包括:
text
Entity
→ 对应数据库表或持久化对象
DTO
→ 接收或传递业务数据
VO
→ 返回给前端的数据
Query
→ 查询条件对象
具体命名规则由项目规范决定。
17. 一个完整请求示例
假设前端发送:
http
GET /api/users/10
Controller:
java
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public UserVO getUser(@PathVariable Long id) {
return userService.getUser(id);
}
}
Service:
java
@Service
public class UserService {
private final UserMapper userMapper;
private final StringRedisTemplate redisTemplate;
public UserService(
UserMapper userMapper,
StringRedisTemplate redisTemplate) {
this.userMapper = userMapper;
this.redisTemplate = redisTemplate;
}
public UserVO getUser(Long id) {
String key = "user:" + id;
String cached = redisTemplate
.opsForValue()
.get(key);
if (cached != null) {
return convertCache(cached);
}
User user = userMapper.selectById(id);
UserVO result = convert(user);
redisTemplate
.opsForValue()
.set(key, serialize(result));
return result;
}
}
执行流程:
text
前端发送 GET /api/users/10
↓
Web 服务器收到请求
↓
DispatcherServlet 分发
↓
UserController.getUser(10)
↓
UserService.getUser(10)
↓
先查询 Redis
↓
缓存未命中
↓
UserMapper 查询数据库
↓
转换为 UserVO
↓
写入 Redis
↓
返回 Controller
↓
序列化为 JSON
↓
返回前端
18. Bean 生命周期中的启动执行
并不是所有业务方法都会在应用启动时执行。
启动阶段主要发生:
text
扫描类
注册 BeanDefinition
创建 Bean
注入依赖
执行初始化方法
启动服务器
注册接口
普通业务方法只有被调用时才会执行。
但以下代码可能在启动阶段运行。
18.1 构造方法
java
@Component
public class InitComponent {
public InitComponent() {
System.out.println("对象被创建");
}
}
18.2 @PostConstruct
java
@Component
public class InitComponent {
@PostConstruct
public void init() {
System.out.println("依赖注入后初始化");
}
}
18.3 CommandLineRunner
java
@Component
public class StartupRunner
implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("应用启动后执行");
}
}
18.4 ApplicationRunner
也可以在 Spring Boot 启动阶段执行自定义逻辑。
19. 开发运行流程
在 IDEA 中启动项目时,一般执行:
text
找到启动类
↓
点击 Run
↓
IDEA 准备 classpath
↓
启动 JVM
↓
JVM 调用 main
↓
SpringApplication.run
↓
Spring Boot 启动
也可以使用 Maven:
bash
mvn spring-boot:run
或者 Maven Wrapper:
Windows:
bash
mvnw.cmd spring-boot:run
Linux/macOS:
bash
./mvnw spring-boot:run
20. 打包流程
执行:
bash
mvn clean package
Maven 会按照生命周期完成:
text
删除旧构建结果
↓
编译主代码
↓
编译测试代码
↓
执行测试
↓
处理资源
↓
生成 Jar
输出通常位于:
text
target/
例如:
text
target/demo-system-1.0.0.jar
21. 部署运行流程
打包后可以执行:
bash
java -jar target/demo-system-1.0.0.jar
JVM 会:
text
读取 Jar
↓
确定主启动类
↓
执行 main
↓
启动 Spring Boot
指定环境:
bash
java -jar demo-system.jar \
--spring.profiles.active=prod
指定端口:
bash
java -jar demo-system.jar \
--server.port=8081
Spring Boot 支持将应用打包为可执行 Jar,并运行自包含应用。
22. 完整全流程总结
整个 Spring Boot 工程的生命周期可以总结为以下五个阶段。
22.1 开发阶段
text
开发者编写:
Java 代码
pom.xml
application.yml
SQL
Mapper
Controller
Service
22.2 Maven 构建阶段
text
IDEA 或命令行调用 Maven
↓
Maven 找到 pom.xml
↓
解析 Starter、驱动和其他依赖
↓
从仓库下载 Jar
↓
建立 classpath
↓
编译项目
22.3 JVM 启动阶段
text
JVM 加载启动类
↓
找到 main 方法
↓
调用 main
↓
创建 SpringApplication
↓
执行 run
22.4 Spring Boot 初始化阶段
text
读取 YAML、环境变量和启动参数
↓
创建 Environment
↓
创建 ApplicationContext
↓
扫描组件
↓
加载自动配置
↓
创建 Bean
↓
完成依赖注入
↓
创建 DataSource
↓
创建 Redis 客户端
↓
创建 Controller、Service、Mapper
↓
启动 Web 服务器
↓
注册 GET、POST 等接口
22.5 业务运行阶段
text
Web 服务器监听端口
↓
前端发送 HTTP 请求
↓
DispatcherServlet 接收请求
↓
找到 Controller
↓
Controller 调用 Service
↓
Service 调用 Mapper 或 Redis
↓
Mapper 查询数据库
↓
结果逐层返回
↓
转换成 JSON
↓
返回前端
23. 最核心的关系
可以将整个体系压缩成以下关系:
text
pom.xml
→ 描述项目需要哪些依赖和如何构建
Maven
→ 下载 Jar、编译、测试和打包
Starter
→ 提供某类功能所需的一组依赖和自动配置入口
驱动或客户端
→ 负责与数据库、Redis 等外部服务真正通信
application.yml
→ 提供端口、地址、用户名、密码等运行参数
JVM
→ 执行 main 方法和 Java 字节码
SpringApplication.run
→ 启动 Spring Boot 应用
ApplicationContext
→ 创建、组装和管理 Bean
依赖注入
→ 将 Bean 提供给需要它的其他 Bean
内嵌 Web 服务器
→ 监听端口并接收 HTTP 请求
DispatcherServlet
→ 将请求分发到对应 Controller
Controller
→ 接收请求和返回结果
Service
→ 执行业务逻辑
Mapper
→ 操作数据库
RedisTemplate 或 RedissonClient
→ 操作 Redis
24. 常见错误理解
24.1 错误:run() 后 Maven 才下载依赖
正确理解:
text
Maven 先下载依赖并编译
JVM 再执行 main 和 run
24.2 错误:有 YAML 就能自动连接数据库
正确理解:
text
对应 Starter
+ 数据库驱动
+ 正确 YAML
+ 自动配置条件满足
+ 数据库服务可用
= 数据库连接可用
24.3 错误:Starter 就是数据库驱动
正确理解:
text
Starter
→ 功能集成和依赖集合
驱动
→ 与具体数据库通信
24.4 错误:所有 Java 类都会自动成为 Bean
正确理解:
只有被扫描、被配置类导入或通过 @Bean 注册的对象,才会由 Spring 管理。
24.5 错误:Spring 注入的是类
正确理解:
text
类
→ Spring 创建对象
→ 对象成为 Bean
→ Bean 被注入
24.6 错误:项目启动后所有 Controller 方法都会执行
正确理解:
Controller 在启动时被创建并注册,但具体接口方法通常只有在对应 HTTP 请求到达后才执行。
25. 结论
Spring Boot 工程并不是单纯依靠一个 main 方法完成全部功能,而是由 Maven、JVM、Spring Framework、Spring Boot、Starter、驱动、配置文件和外部服务共同协作。
其核心思想是:
text
Maven 负责准备程序
JVM 负责执行程序
Spring Boot 负责启动和自动配置
Spring 容器负责管理对象
Web 服务器负责接收请求
业务分层负责处理请求
驱动和客户端负责访问外部系统
最终形成一个高度集成的开发与运行体系:
text
项目声明依赖
↓
Maven 下载并构建
↓
JVM 执行启动类
↓
Spring Boot 读取配置
↓
Spring 创建并注入 Bean
↓
自动配置数据库、Redis 和 Web 组件
↓
服务器监听 HTTP 请求
↓
Controller、Service、Mapper 完成业务处理
↓
返回响应结果
这就是一个典型 Spring Boot 工程从开发、构建、启动到运行和部署的完整流程。