Spring Boot 工程开发全流程说明

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/javasrc/main/resourcessrc/test/javatarget 等标准目录。


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 使用构建生命周期组织编译、测试、打包和安装等阶段。常见生命周期命令包括 cleancompiletestpackageinstall

例如:

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 工程从开发、构建、启动到运行和部署的完整流程。

相关推荐
xianjixiance_1 小时前
HarmonyOS应用开发实战:萌宠日记 - 整体架构设计与技术选型解析
后端
掘金者阿豪1 小时前
数据库优化器到底在想什么:一个SQL今天能跑明天崩的背后
后端
b130538100491 小时前
HarmonyOS应用开发实战:萌宠日记 - 回调函数模式
后端
Conan在掘金2 小时前
鸿蒙报错速查:Cannot find name 'image',忘 import 编译就炸,根因 + 真解法
后端
雪隐2 小时前
个人电脑玩AI-13让5060 Ti给你打工——我用 0.9B 小模型终结了"谁来记会议纪要"这个世纪难题
前端·人工智能·后端
无名之辈J2 小时前
Ai开发
后端
Conan在掘金2 小时前
�鸿蒙报错速查:arkts-strict-typing 函数返回值类型必须显式,忘标就炸,根因 + 真解法
后端
半个落月2 小时前
用 LangChain JS 做可控写作实验:理解温度参数、提示词与异步调用
javascript·人工智能·后端
爱勇宝2 小时前
《道德经》第 7 章:真正厉害的领导者,不抢主角
前端·后端·程序员