7-[SpringBoot 启航] 快速入门与核心原理

1. [SpringBoot 启航] 快速入门与核心原理

摘要: 本章将引导您迈出 Spring Boot 开发的第一步。我们将使用官方脚手架快速搭建并运行一个 Web 服务,理解其便捷部署的原理,并深入剖析 Spring Boot 两大核心特性——启动器 (Starter)自动配置 (Auto-configuration)

1.1. Spring Boot 快速部署

在开始动手之前,我们先花一分钟了解现代 Web 应用的主流架构模式,这将帮助我们理解为何 Spring Boot 的设计如此契合当下的开发需求。

1.1.1. 现代 Web 架构:前后端分离简介

现代 Web 开发大多采用 前后端分离 的模式。在这种架构下,前端(通常由 Vue, React, Angular 等框架构建)和后端(我们的 Spring Boot 应用)是两个独立的项目。

  • 后端 (Backend): 不再负责渲染 HTML 页面。它的核心职责是提供一套 API 接口(通常是 RESTful API),处理业务逻辑,操作数据库,并以统一的数据格式(如 JSON)返回结果。
  • 前端 (Frontend): 负责用户界面的展示和交互。它通过调用后端的 API 接口获取数据,然后将数据动态地渲染到页面上。

这种模式带来了职责清晰、开发高效、技术栈灵活等诸多好处。我们的教程将完全基于这种前后端分离的模式进行。


1.1.2. [实践] 使用 Spring Initializr 创建第一个 Web 应用

现在,我们来实现第一个需求:创建一个 Web 服务,当用户访问 http://localhost:8080/hello 时,页面显示 “Hello, Spring Boot!”

创建 Spring Boot 项目最快、最标准的方式是使用官方的 Spring Initializr (俗称“脚手架”)。

1. 使用 Idea 生成项目

  • 配置选项:
    • Project: Maven
    • Language: Java
    • Spring Boot: 3.3.3 (或更高稳定版)
    • Project Metadata:
      • Group: com.example
      • Artifact: spring-boot-demo
      • Packaging: Jar
      • Java: 17 (Spring Boot 3.x 要求 JDK 17+)
    • Dependencies: 点击 “ADD DEPENDENCIES…”,搜索并添加 Spring Web

配置完成后,点击 “GENERATE” 按钮,下载项目压缩包并用 IDEA 打开。

image-20250814091918843

2. 剖析项目结构与 pom.xml

IDEA 加载完成后,您会看到一个标准的 Maven 项目结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
. 📂 spring-boot-demo
├── 📄 pom.xml <- 核心依赖管理
└── 📂 src
├── 📂 main
│ ├── 📂 java
│ │ └── 📂 com/example/springbootdemo/
│ │ └── 📄 SpringBootDemoApplication.java <- 启动类
│ └── 📂 resources
│ └── 📄 application.properties <- 核心配置文件
└── 📂 test
└── 📂 java
└── 📂 com/example/springbootdemo/
└── 📄 SpringBootDemoApplicationTests.java

我们重点关注 pom.xml 中的两个核心配置:

文件路径: spring-boot-demo/pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

1.1.3. [实践] 编写 @RestController 并运行服务

1. 编写 Controller

文件路径: src/main/java/com/example/springbootdemo/controller/HelloController.java (新增文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.springbootdemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @RestController 是一个组合注解,相当于 @Controller + @ResponseBody
* @Controller: 声明这是一个处理 HTTP 请求的控制器 Bean
* @ResponseBody: 告诉 Spring MVC,这个类中所有方法的返回值都应直接写入 HTTP 响应体中
* (对于前后端分离项目,通常就是返回 JSON 或纯文本)
*/
@RestController
public class HelloController {

/**
* @GetMapping("/hello"): 将此方法映射到处理 GET 方式的 "/hello" 请求
*/
@GetMapping("/hello")
public String sayHello() {
return "Hello, Spring Boot!";
}
}

重要: 我们自己创建的类(如 Controller, Service)必须放在 启动类 SpringBootDemoApplication.java 所在的包或其子包 下,才能被 Spring Boot 默认的组件扫描机制发现。

2. 运行与验证

现在,找到 SpringBootDemoApplication.java,直接右键运行其 main 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
// SpringBootDemoApplication.java
package com.example.springbootdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
// 启动 Spring Boot 应用
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}

当控制台输出 Tomcat started on port(s): 8080 (http) 时,表示服务已成功启动。

打开浏览器,访问 http://localhost: 8080/hello。


1.2. 便捷的部署与执行

Spring Boot 极大地简化了应用的部署过程,其核心就是 可执行 JAR 包

1.2.1. [实践] 打包为可执行 Fat JAR

在 IDEA 的 Maven 窗口中,执行 package 命令。

打包成功后,在 target 目录下会生成一个 spring-boot-demo-0.0.1-SNAPSHOT.jar 文件。将这个 JAR 包复制到 任何安装了 Java 17+ 环境 的机器上,在命令行中执行:

1
java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar
1
2
3
4
5
6
7
8
9
10
11
12
  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.3)

... (省略日志)
...
2025-08-14T21:30:00.123Z INFO 12345 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
...

服务再次启动!这证明了 Spring Boot 应用的 可移植性,无需外部的 Tomcat 服务器。


1.2.2. Spring Boot JAR 与普通 JAR 的区别

为什么 Spring Boot 的 JAR 包可以直接运行,而普通的 JAR 包不行?

面试官深度辨析
今天 晚上 9:45

Spring Boot 打包的“Fat JAR”和我们平时用的普通 JAR,在结构上有什么本质区别?

求职者

最大的区别在于内容。普通 JAR 只包含我们自己编写的 .class 文件和资源。而 Spring Boot 的 Fat JAR 除了包含我们自己的代码,还内置了三样关键东西:

求职者

1.所有运行时依赖 : 所有的第三方 JAR 包(如 Spring MVC, Tomcat, Jackson)都被打包进来了。

求职者

2.内嵌的 : Tomcat 服务器的 JAR 包也被包含在内。

求职者

3.一个特殊的启动器类 :Spring Boot 提供了一个 JarLauncher 类,它知道如何正确地加载所有内嵌的依赖并启动应用。

非常好。所以,可执行性就是这么来的?

求职者

是的。Fat JAR 的 MANIFEST.MF 文件中,Main-Class 被指向了这个 JarLauncher。所以当我们执行 java -jar 时,实际上是 JarLauncher 在工作,它创建了一个特殊的类加载器来加载 BOOT-INF/lib/ 下的依赖,然后才调用我们自己写的 main 方法。而普通 JAR 没有这个机制。


1.3. 自动配置核心揭秘

我们已经体验到了 Spring Boot 的便捷,现在是时候揭开其背后的魔法了。

1.3.1. [面试题] SpringApplication.run() 背后发生了什么?

面试官深度剖析
昨天 上午 10:00

当我们执行 SpringApplication.run(MyApplication.class, args) 这一行代码时,Spring Boot 在背后都做了哪些核心工作?

求职者

这是一个经典的启动流程问题。概括来说,它主要做了四件大事:

求职者

1.推断应用类型 : Spring Boot 会检查类路径,判断这是一个标准的 Servlet Web 应用,还是一个响应式的 WebFlux 应用,或是一个非 Web 应用。

求职者

2.加载自动配置类 : 这是最核心的一步。它会从所有依赖的 JAR 包中,找到 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,加载里面定义的所有自动配置类。

求职者

3.创建并准备IoC容器 : 创建一个 ApplicationContext 实例,然后执行一系列的准备工作,比如加载我们的主配置类 (MyApplication.class),将命令行参数 args 注册为 Bean 等。

求职者

4.刷新容器并启动组件 : “刷新” 容器是 Spring 的一个术语,它会触发所有 Bean 的实例化、依赖注入、初始化等过程。在这个过程中,之前加载的自动配置类会根据条件 (@ConditionalOn...) 判断是否生效。对于 Web 应用,此阶段还会启动内嵌的 Tomcat 服务器。


1.3.2. 魔法的起点:@SpringBootApplication 注解剖析

我们可以在 SpringBootDemoApplication 里面找到这个注解,那么这个注解的作用是什么?

SpringApplication.run() 的所有行为,都源于启动类上的 @SpringBootApplication 注解。它是一个复合注解,由三个核心注解组成:

  • @SpringBootConfiguration:
    • 它本身被 @Configuration 注解,所以 Spring Boot 的主启动类本质上就是一个 Java 配置类。这意味着我们可以在启动类中直接定义 @Bean
  • @EnableAutoConfiguration:
    • 启用自动配置。这是 Spring Boot 最神奇的地方。它会触发上面提到的“加载自动配置类”的流程。
  • @ComponentScan:
    • 启用组件扫描。它告诉 Spring 去哪里查找我们自己定义的 Bean(如 @Component, @Service, @RestController 等)。默认的扫描路径是 启动类所在的包及其所有子包

1.3.3. 按需加载:条件注解 (@ConditionalOn...) 的作用

@EnableAutoConfiguration 虽然加载了所有可能的自动配置类,但并非所有都会生效。每个自动配置类都被一系列的 条件注解 (@ConditionalOn...) 所保护。

工作原理:
Spring Boot 在处理自动配置类时,会检查其上的条件注解。只有当所有条件都满足时,这个配置类才会生效

常用条件注解:

注解作用
@ConditionalOnClass当类路径下 存在 指定的类时,配置生效。 (这是最常用的)
@ConditionalOnMissingClass当类路径下 不存在 指定的类时,配置生效。
@ConditionalOnBean当 IoC 容器中 存在 指定的 Bean 时,配置生效。
@ConditionalOnMissingBean当 IoC 容器中 不存在 指定的 Bean 时,配置生效。 (常用于提供默认 Bean)
@ConditionalOnPropertyapplication.properties存在 指定的配置项时,配置生效。
@ConditionalOnWebApplication仅当当前应用是 Web 应用 时,配置生效。

示例:
WebMvcAutoConfiguration (Spring MVC 的自动配置) 的部分源码:

1
2
3
4
5
6
7
8
// 只有当应用是 Servlet Web 应用,并且类路径下存在 Servlet, DispatcherServlet, WebMvcConfigurer 时,
// 并且容器中还没有用户自定义的 WebMvcConfigurationSupport Bean,此配置才会生效。
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
public class WebMvcAutoConfiguration {
// ...
}