文章目录
-
- [1. 课前导读](#1. 课前导读)
- [2. 知识目标](#2. 知识目标)
- [3. 理论讲解](#3. 理论讲解)
-
- [3.1 为什么Spring Boot 4.x是一次"代际升级"](#3.1 为什么Spring Boot 4.x是一次“代际升级”)
- [3.2 Spring Boot 4.x 五大核心新特性](#3.2 Spring Boot 4.x 五大核心新特性)
- [3.3 Spring Boot 4.x vs 3.x 关键差异对比](#3.3 Spring Boot 4.x vs 3.x 关键差异对比)
- [3.4 环境要求详解](#3.4 环境要求详解)
- [4. 环境搭建](#4. 环境搭建)
-
- [4.1 方式一:使用Spring Initializr(推荐)](#4.1 方式一:使用Spring Initializr(推荐))
- [4.2 方式二:手动创建Maven项目](#4.2 方式二:手动创建Maven项目)
- [4.3 方式三:使用Maven Wrapper(可选)](#4.3 方式三:使用Maven Wrapper(可选))
- [4.4 Gradle配置(备选)](#4.4 Gradle配置(备选))
- [5. 代码实战](#5. 代码实战)
-
- [5.1 启动类:HelloSpringBootApplication.java](#5.1 启动类:HelloSpringBootApplication.java)
- [5.2 REST Controller:HelloController.java](#5.2 REST Controller:HelloController.java)
- [5.3 运行与测试](#5.3 运行与测试)
- [6. 底层源码剖析](#6. 底层源码剖析)
-
- [6.1 Spring Boot 4.x 启动流程源码概览](#6.1 Spring Boot 4.x 启动流程源码概览)
- [6.2 自动配置的模块化加载](#6.2 自动配置的模块化加载)
- [6.3 虚拟线程的自动配置源码](#6.3 虚拟线程的自动配置源码)
- [7. 常见坑点与生产问题排查](#7. 常见坑点与生产问题排查)
-
- [坑点1:使用 spring-boot-starter-web 而非 webmvc](#坑点1:使用 spring-boot-starter-web 而非 webmvc)
- 坑点2:Java版本不兼容
- [坑点3:Jackson 3包名迁移导致编译错误](#坑点3:Jackson 3包名迁移导致编译错误)
- 坑点4:虚拟线程与ThreadLocal的兼容性问题
- [坑点5:IntelliJ IDEA版本过低](#坑点5:IntelliJ IDEA版本过低)
- [8. 本章总结](#8. 本章总结)
- [9. 课后作业](#9. 课后作业)
- [🔗 SpringBoot 4.x 从入门到企业级实战系列课程](#🔗 SpringBoot 4.x 从入门到企业级实战系列课程)

本文是《SpringBoot 4.x 从入门到精通》系列第1课,全文约13000字,建议阅读时间50分钟。
环境要求:Spring Boot 4.x,Spring Framework 7,Java 17+(推荐Java 21/25)
1. 课前导读
2025年11月20日,Spring Boot 4.0.0正式发布。这不是一次常规的版本迭代,而是继Spring Boot 2.x到3.x(javax→jakarta命名空间迁移)之后,框架历史上又一次重大重构。Spring Boot 4.0基于全新的Spring Framework 7.0构建,在模块化架构、空安全、虚拟线程、API版本控制等多个维度带来了根本性的变化。
对于Java后端开发者而言,掌握Spring Boot 4.x不再是"加分项",而是生存技能。Spring Boot 3.5.x的开源支持已于2026年6月终止,3.5及更早的3.x版本不再收到社区安全补丁和Bug修复。这意味着,迁移到4.x已经不是"要不要做"的问题,而是"什么时候做"的问题。
本节课是整个系列的开篇,目标是帮助你从零开始完成Spring Boot 4.x的环境搭建,理解4.x相比3.x的核心变化,并写出第一个可运行的HelloWorld程序。如果你已经是Spring Boot 3.x的使用者,这节课会让你清晰地看到4.x带来的突破;如果你是初学者,这节课将为你打下坚实的起点。
前置知识:Java基础语法、Maven或Gradle基本使用。如果对Spring框架的IoC概念有所了解,学习体验会更好,但不是必须的。
学习难点:理解Spring Boot 4.x的模块化设计理念;区分4.x和3.x在依赖坐标、配置方式上的差异;虚拟线程在Spring Boot 4.x中的默认行为。
【配图描述:Spring Boot 4.x 版本演进时间线------从2014年Spring Boot 1.0到2025年Spring Boot 4.0的关键里程碑】
2. 知识目标
学完本节课,你必须掌握以下核心知识点:
- Spring Boot 4.x 五大核心新特性:代码库模块化、JSpecify空安全、虚拟线程默认化、原生API版本控制、Jackson 3升级。
- 环境要求与搭建:Java 17+(推荐21/25)、Maven 3.6.3+或Gradle 8.14+、IntelliJ IDEA 2025.3+,以及Spring Initializr的正确使用方式。
- 第一个Spring Boot 4.x项目:完整可运行的HelloWorld Web应用,包括Maven pom.xml配置、启动类编写、REST Controller编写。
- 4.x vs 3.x 关键差异:Starter模块化的影响、webmvc starter替代web starter、Jackson包名迁移、虚拟线程默认开启。
- Spring Boot 4.x 底层启动机制初步理解:自动配置的模块化加载、ServletWebServerFactory的初始化流程。
3. 理论讲解
3.1 为什么Spring Boot 4.x是一次"代际升级"
Spring Boot 4.0于2025年11月20日正式发布,基于Spring Framework 7.0构建,是自Spring Boot 3.0以来最重要的版本发布。这次升级不是简单地把版本号从3变成4,而是从架构层面重新设计了框架的组织方式。
Spring Boot 3.0的核心变化是javax→jakarta命名空间迁移,属于"被动适配"。而Spring Boot 4.0的变化是主动重构:框架团队对代码库进行了完整模块化,将原来庞大的spring-boot-autoconfigure单体JAR拆分为多个聚焦的小模块,每个模块只包含特定技术领域的自动配置类。
这一变化带来的直接影响是:应用只加载真正需要的自动配置类,减少了类路径扫描的开销,启动更快,内存占用更低。根据实测数据,Spring Boot 4.0相比3.5.6,容器镜像体积减少了约19%。
【配图描述:Spring Boot 3.x单体自动配置 vs 4.x模块化自动配置对比图】
3.2 Spring Boot 4.x 五大核心新特性
特性一:代码库完整模块化。 Spring Boot 4.0将单体的自动配置JAR拆分为多个轻量模块。例如,spring-boot-starter-web在4.x中被拆分,Web MVC项目推荐使用更聚焦的spring-boot-starter-webmvc。框架为每个模块提供了独立的org.springframework.boot.<module>包空间,提高了代码的组织性和可维护性。
特性二:JSpecify空安全。 Spring Boot 4.0在整个产品组合中引入了JSpecify注解,实现标准化的空值安全。默认情况下,Spring API的返回值和参数都标记为非null,可空的用@Nullable显式标注。IntelliJ IDEA 2025.3+已经支持这些注解,可以在编译期发出警告,帮助开发者在编码阶段就发现潜在的NullPointerException风险。
特性三:虚拟线程默认化。 这是对应用架构影响最深远的变化。在Java 21+环境中,spring.threads.virtual.enabled的默认值在Spring Boot 4.0中变为true,Tomcat和Jetty的请求处理线程默认使用虚拟线程,@Async任务和定时任务也遵循同一模型。虚拟线程采用M:N调度模型,大量虚拟线程挂载在少量平台线程上,切换成本极低,使得同步代码就能达到接近响应式框架的吞吐量。
特性四:原生API版本控制。 Spring Framework 7在Spring MVC和Spring WebFlux中均提供了原生的API版本控制支持,框架支持基于路径、头信息、查询参数和媒体类型的版本控制策略。开发者只需在映射注解上声明版本号即可,不再需要手动编写版本路由逻辑。
特性五:Jackson 3升级。 Spring Boot 4.0将Jackson 3作为默认JSON处理库,Jackson 2.x以deprecated形式保留。Jackson 3的包名从com.fasterxml.jackson迁移到了tools.jackson,API也有变化。
3.3 Spring Boot 4.x vs 3.x 关键差异对比
| 对比维度 | Spring Boot 3.x | Spring Boot 4.x |
|---|---|---|
| 底层框架 | Spring Framework 6.x | Spring Framework 7.0 |
| 最低Java版本 | Java 17 | Java 17(推荐21/25) |
| 模块化 | 单体autoconfigure JAR | 拆分为多个聚焦模块 |
| 虚拟线程 | opt-in实验特性 | 默认启用(Java 21+) |
| JSON库 | Jackson 2.x | Jackson 3(包名tools.jackson) |
| 空安全 | 无统一标准 | JSpecify全产品组合覆盖 |
| Web Starter | spring-boot-starter-web | spring-boot-starter-webmvc |
| API版本控制 | 需第三方库 | 框架原生支持 |
| GraalVM | 实验特性 | 正式生产级支持(GraalVM 25+) |
| Undertow | 支持 | 已移除(需Servlet 6.1) |
破坏性变更提醒:Undertow和Jersey在4.0中已被移除,因为Spring Boot 4要求Servlet 6.1基线,而Undertow尚不兼容。如果你的项目使用了Undertow,需要迁移到Tomcat或Jetty。
3.4 环境要求详解
Spring Boot 4.0.8的系统要求如下:
- Java:最低Java 17,兼容至Java 26。推荐使用Java 21或Java 25以获得最佳体验和长期支持。
- Spring Framework:7.0.9或以上版本。
- Maven:3.6.3或更高版本(推荐3.9.x)。
- Gradle:8.14+(推荐Gradle 9)。
- IDE:IntelliJ IDEA 2025.3或更高版本,该版本已原生支持Spring Boot 4和Spring Framework 7。
Spring Boot 4.x的系统要求明确要求Java 17起步,不兼容Java 16或更早版本。这一策略符合现代Java生态的发展节奏。Java 21作为LTS版本是当前最稳妥的选择;如果你希望使用最新的虚拟线程和ZGC优化,Java 25是更好的选项。
【配图描述:Spring Boot 4.x 环境要求一览图,包含Java、Maven、Gradle、IDE的版本要求】
4. 环境搭建
4.1 方式一:使用Spring Initializr(推荐)
Spring Initializr是Spring官方提供的项目生成器,是创建Spring Boot项目最快的方式。
步骤1 :访问 https://start.spring.io
步骤2:配置项目参数
| 配置项 | 推荐值 |
|---|---|
| Project | Maven |
| Language | Java |
| Spring Boot | 4.0.x(最新稳定版) |
| Group | com.example |
| Artifact | hello-spring-boot4 |
| Name | hello-spring-boot4 |
| Package name | com.example.helloboot |
| Packaging | Jar |
| Java | 21 |
步骤3 :添加依赖------选择"Spring Web"(注意:在Spring Boot 4.x中,这会生成spring-boot-starter-webmvc依赖)。
步骤4:点击"GENERATE"下载项目ZIP包,解压后用IntelliJ IDEA打开。
【配图描述:Spring Initializr页面截图,标注关键配置区域】
4.2 方式二:手动创建Maven项目
为了让你真正理解Spring Boot 4.x的项目结构,这里采用手动创建Maven项目的方式。
步骤1:创建项目目录结构
hello-spring-boot4
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── example
│ └── helloboot
│ ├── HelloSpringBootApplication.java
│ └── controller
│ └── HelloController.java
└── resources
└── application.yml
步骤2:编写pom.xml
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 使用 Spring Boot 4.x Parent 统一管理依赖和插件版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.6</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello-spring-boot4</name>
<description>第一个 Spring Boot 4.x Web MVC 接口示例</description>
<properties>
<!-- Spring Boot 4.x 至少要求 Java 17,这里推荐使用 Java 21 -->
<java.version>21</java.version>
</properties>
<dependencies>
<!--
Spring Boot 4.x Web MVC 新项目推荐使用更聚焦的 webmvc starter。
注意:这与 3.x 中的 spring-boot-starter-web 不同!
4.x 将 web 模块进一步细分为 webmvc、webflux 等。
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!-- 与 Web MVC 模块配套的测试 Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven 插件,用于打包和运行应用 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
关键差异说明 :在Spring Boot 3.x中,Web项目使用spring-boot-starter-web。但在4.x中,由于模块化重构,推荐使用spring-boot-starter-webmvc,测试依赖也相应变为spring-boot-starter-webmvc-test。
步骤3:编写application.yml
yaml
# application.yml
server:
port: 8080
spring:
application:
name: hello-spring-boot4
# Spring Boot 4.x 中虚拟线程默认启用(Java 21+环境)
# 如需显式声明,可以添加以下配置:
# spring:
# threads:
# virtual:
# enabled: true
4.3 方式三:使用Maven Wrapper(可选)
Spring Initializr生成的项目会自动包含Maven Wrapper。Spring Boot 4.0使用Maven Wrapper 3.3.4。如果你手动创建项目,可以运行以下命令生成Wrapper:
bash
mvn wrapper:wrapper -Dmaven=3.9.9
之后使用./mvnw(Linux/Mac)或mvnw.cmd(Windows)代替mvn命令,无需本地安装Maven。
4.4 Gradle配置(备选)
如果你偏好Gradle,build.gradle配置如下:
groovy
plugins {
id 'java'
id 'org.springframework.boot' version '4.0.6'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
}
tasks.named('test') {
useJUnitPlatform()
}
5. 代码实战
5.1 启动类:HelloSpringBootApplication.java
java
package com.example.helloboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot 4.x 应用启动入口。
*
* @SpringBootApplication 是一个组合注解,包含:
* - @SpringBootConfiguration:标识这是一个配置类
* - @EnableAutoConfiguration:启用自动配置(4.x中基于模块化加载)
* - @ComponentScan:扫描当前包及子包下的组件
*/
@SpringBootApplication
public class HelloSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(HelloSpringBootApplication.class, args);
}
}
代码解读 :@SpringBootApplication在4.x中与3.x保持一致,但其底层的自动配置机制已经发生了根本变化。在3.x中,@EnableAutoConfiguration会加载一个庞大的spring.factories文件中的所有自动配置类;在4.x中,自动配置被分散到各个模块中,每个模块只加载自己负责的自动配置,减少了不必要的类加载。
5.2 REST Controller:HelloController.java
java
package com.example.helloboot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.Map;
/**
* 第一个 Spring Boot 4.x REST Controller。
*
* @RestController = @Controller + @ResponseBody
* 返回值自动序列化为 JSON(4.x 中默认使用 Jackson 3)
*/
@RestController
public class HelloController {
/**
* 最简单的 Hello 接口。
*
* 访问方式:GET http://localhost:8080/hello
*/
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot 4.x!";
}
/**
* 带参数的 Hello 接口。
*
* 访问方式:GET http://localhost:8080/greet?name=World
*/
@GetMapping("/greet")
public String greet(@RequestParam(defaultValue = "World") String name) {
return "Hello, " + name + "! Welcome to Spring Boot 4.x.";
}
/**
* 返回 JSON 格式的接口信息。
*
* 访问方式:GET http://localhost:8080/info
* 返回示例:
* {
* "framework": "Spring Boot 4.x",
* "javaVersion": "21",
* "virtualThreadEnabled": true,
* "serverTime": "2025-12-01T10:30:00"
* }
*/
@GetMapping("/info")
public Map<String, Object> info() {
return Map.of(
"framework", "Spring Boot 4.x",
"javaVersion", System.getProperty("java.version"),
"virtualThreadEnabled", isVirtualThreadEnabled(),
"serverTime", LocalDateTime.now().toString()
);
}
/**
* 验证虚拟线程是否生效的接口。
* 在 Java 21+ 环境中,Spring Boot 4.x 默认启用虚拟线程,
* 该接口会返回当前线程是否为虚拟线程。
*
* 访问方式:GET http://localhost:8080/thread
*/
@GetMapping("/thread")
public Map<String, Object> threadInfo() {
Thread currentThread = Thread.currentThread();
return Map.of(
"threadName", currentThread.getName(),
"isVirtual", currentThread.isVirtual(),
"threadClass", currentThread.getClass().getName()
);
}
/**
* 判断虚拟线程是否启用的辅助方法。
* 在 Spring Boot 4.x 中,如果 Java 版本 >= 21 且
* spring.threads.virtual.enabled 未显式设为 false,
* 则虚拟线程默认启用。
*/
private boolean isVirtualThreadEnabled() {
try {
// Java 21+ 中 Thread.isVirtual() 方法可用
Thread.ofVirtual().start(() -> {});
return true;
} catch (UnsupportedOperationException e) {
return false;
}
}
}
5.3 运行与测试
步骤1:启动应用
在IntelliJ IDEA中,直接运行HelloSpringBootApplication的main方法。或者在项目根目录下执行:
bash
./mvnw spring-boot:run
步骤2:观察启动日志
成功启动后,控制台会输出类似以下内容:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v4.0.6)
2025-12-01 10:30:00 [main] INFO c.e.h.HelloSpringBootApplication -
Starting HelloSpringBootApplication using Java 21 with PID 12345
2025-12-01 10:30:00 [main] INFO c.e.h.HelloSpringBootApplication -
The following 1 profile is active: "default"
2025-12-01 10:30:01 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer -
Tomcat initialized with port(s): 8080 (http)
2025-12-01 10:30:01 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer -
Tomcat started on port(s): 8080 (http) with context path ''
注意日志中的Tomcat initialized with port(s): 8080,在Spring Boot 4.x中,Tomcat的请求处理线程默认使用虚拟线程。
步骤3:测试接口
使用浏览器或curl命令测试:
bash
# 测试 /hello 接口
curl http://localhost:8080/hello
# 输出:Hello, Spring Boot 4.x!
# 测试 /greet 接口
curl "http://localhost:8080/greet?name=Developer"
# 输出:Hello, Developer! Welcome to Spring Boot 4.x.
# 测试 /info 接口
curl http://localhost:8080/info
# 输出:{"framework":"Spring Boot 4.x","javaVersion":"21","virtualThreadEnabled":true,"serverTime":"2025-12-01T10:30:00"}
# 测试 /thread 接口(验证虚拟线程)
curl http://localhost:8080/thread
# 输出:{"threadName":"","isVirtual":true,"threadClass":"java.lang.VirtualThread"}
关键验证 :访问/thread接口,如果返回"isVirtual":true和"threadClass":"java.lang.VirtualThread",说明虚拟线程已经生效。在Spring Boot 4.x + Java 21环境中,这是默认行为,无需任何额外配置。
【配图描述:IntelliJ IDEA中运行Spring Boot 4.x应用的截图,标注启动日志中的关键信息】
6. 底层源码剖析
6.1 Spring Boot 4.x 启动流程源码概览
Spring Boot 4.x的启动入口仍然是SpringApplication.run()方法,但底层的自动配置加载机制发生了显著变化。
java
// 源码路径:org.springframework.boot.SpringApplication
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return new SpringApplication(primarySource).run(args);
}
在SpringApplication的构造函数中,4.x版本进行了重要的模块化调整:
java
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 推断应用类型:SERVLET / REACTIVE / NONE
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 加载 BootstrapRegistryInitializer(4.x 中模块化加载)
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class)
);
// 设置初始器和监听器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
与3.x的关键差异在于:getSpringFactoriesInstances()方法在4.x中会从多个模块的META-INF/spring/目录 加载配置,而非3.x中单一的spring.factories文件。
6.2 自动配置的模块化加载
Spring Boot 4.x将自动配置的加载机制从"集中式"改为"分布式"。在3.x中,所有的自动配置类都声明在spring-boot-autoconfigure模块的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中。而在4.x中,每个模块(如spring-boot-webmvc、spring-boot-jdbc等)都有自己的自动配置声明文件。
java
// 源码路径:org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
// 4.x 中该方法会扫描所有模块的 AutoConfiguration.imports 文件
protected List<String> getCandidateConfigurations(
AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = ImportCandidates.load(
AutoConfiguration.class,
getBeanClassLoader()
).getCandidates();
return configurations;
}
ImportCandidates.load()方法会从classpath中所有JAR包的META-INF/spring/目录下查找AutoConfiguration.imports文件,汇总所有模块的自动配置类。这意味着应用只需要加载实际引入的模块中的自动配置,未引入的模块的自动配置类完全不会出现在classpath中。
6.3 虚拟线程的自动配置源码
Spring Boot 4.x中虚拟线程的启用由VirtualThreadsAutoConfiguration负责:
java
// 源码路径:org.springframework.boot.autoconfigure.thread.Threading
@AutoConfiguration
@ConditionalOnProperty(
prefix = "spring.threads.virtual",
name = "enabled",
havingValue = "true",
matchIfMissing = true // 4.x 默认启用!
)
@ConditionalOnJava(range = JavaVersion.TWENTY_ONE_AND_LATER)
public class VirtualThreadsAutoConfiguration {
@Bean
@ConditionalOnThreading(Threading.VIRTUAL)
public TomcatProtocolHandlerCustomizer<?>
protocolHandlerVirtualThreadExecutorCustomizer() {
return protocolHandler -> {
protocolHandler.setExecutor(
Executors.newVirtualThreadPerTaskExecutor()
);
};
}
}
关键点:matchIfMissing = true意味着在Spring Boot 4.x中,如果用户没有显式配置spring.threads.virtual.enabled,虚拟线程默认启用。@ConditionalOnJava(range = JavaVersion.TWENTY_ONE_AND_LATER)确保只有在Java 21+环境中才会启用虚拟线程,Java 17环境仍然使用平台线程。
7. 常见坑点与生产问题排查
坑点1:使用 spring-boot-starter-web 而非 webmvc
报错现象:项目可以启动,但IDE提示依赖已废弃。
原因 :Spring Boot 4.x模块化重构后,spring-boot-starter-web被标记为deprecated,新项目推荐使用spring-boot-starter-webmvc。
解决方案 :将spring-boot-starter-web替换为spring-boot-starter-webmvc,测试依赖替换为spring-boot-starter-webmvc-test。
坑点2:Java版本不兼容
报错现象 :java.lang.UnsupportedClassVersionError 或编译失败。
原因:Spring Boot 4.x最低要求Java 17,如果本地JDK版本低于17,无法编译运行。
解决方案 :检查java -version输出,升级到Java 21或25。在IntelliJ IDEA中,检查Project Structure → SDK设置和Maven Runner的JRE设置。
坑点3:Jackson 3包名迁移导致编译错误
报错现象 :import com.fasterxml.jackson.databind.ObjectMapper; 编译失败。
原因 :Spring Boot 4.x默认使用Jackson 3,包名从com.fasterxml.jackson迁移到了tools.jackson。
解决方案 :将自定义Jackson配置中的import语句从com.fasterxml.jackson.*改为tools.jackson.*。Jackson 2和3可以在同一个项目中共存,但需要显式声明Jackson 2依赖。
坑点4:虚拟线程与ThreadLocal的兼容性问题
报错现象:ThreadLocal中的值在不同请求间出现"串数据"现象。
原因:虚拟线程可以创建数百万实例,ThreadLocal的清理策略需要重新审视。如果ThreadLocal使用后未清理,可能导致内存泄漏或数据污染。
解决方案 :在虚拟线程环境中,优先使用ScopedValue(Java 21+预览特性)替代ThreadLocal,或确保在finally块中调用ThreadLocal.remove()。
坑点5:IntelliJ IDEA版本过低
报错现象:Spring Boot 4.x项目无法被IDE正确识别,自动配置提示不工作。
原因:Spring Boot 4和Spring Framework 7需要IntelliJ IDEA 2025.3或更高版本才能获得完整的IDE支持。
解决方案:升级IntelliJ IDEA到2025.3+版本。
8. 本章总结
本节课作为Spring Boot 4.x系列的开篇,完成了从环境搭建到第一个可运行应用的完整流程。核心要点如下:
五大新特性:Spring Boot 4.x带来了代码库模块化(更小更聚焦的JAR)、JSpecify空安全(编译期空值检查)、虚拟线程默认化(Java 21+环境下同步代码达到响应式性能)、原生API版本控制(框架级支持)、Jackson 3升级(包名tools.jackson)。
环境要求:Java 17起步,推荐21/25;Maven 3.6.3+或Gradle 8.14+;IntelliJ IDEA 2025.3+。Spring Boot 3.5.x已停止开源支持,迁移到4.x是必然选择。
关键差异 :Web项目使用spring-boot-starter-webmvc替代spring-boot-starter-web;虚拟线程在Java 21+环境中默认启用;Jackson 3的包名迁移是最大的破坏性变更之一。
源码洞察 :Spring Boot 4.x的自动配置从集中式加载改为分布式加载,每个模块独立管理自己的自动配置类,ImportCandidates.load()方法负责汇总所有模块的配置。
9. 课后作业
基础题1
在本地环境中分别使用Java 17、Java 21和Java 25运行本节课的HelloWorld项目,观察以下差异:
- 启动日志中Tomcat的线程模型描述是否不同
- 访问
/thread接口,分别返回什么结果 - 在
pom.xml中将java.version分别设为17、21、25,记录编译和运行结果
提示 :Java 17环境下,虚拟线程不可用,/thread接口应返回"isVirtual":false。
基础题2
修改HelloController,添加一个新的接口/version,返回当前应用的Spring Boot版本号。提示:可以通过SpringBootVersion.getVersion()(位于org.springframework.boot.SpringBootVersion)获取版本信息,返回JSON格式。
综合实战题
创建一个新的Spring Boot 4.x项目(使用Spring Initializr),实现一个简单的"待办事项"REST API:
- 技术栈:Spring Boot 4.x + spring-boot-starter-webmvc
- 数据存储 :使用
ConcurrentHashMap在内存中存储待办事项(无需数据库) - 接口设计 :
GET /api/todos:获取所有待办事项POST /api/todos:创建新的待办事项(接收JSON请求体)GET /api/todos/{id}:根据ID获取待办事项DELETE /api/todos/{id}:删除待办事项
- 实体类 :
Todo包含id(Long)、title(String)、completed(Boolean)、createdAt(LocalDateTime) - 验证虚拟线程 :添加一个
GET /api/todos/thread-info接口,返回当前处理请求的线程信息
要求:
- 使用
@RestController和@RequestMapping注解 - 使用
@RequestBody接收JSON请求 - 使用
@PathVariable和@RequestParam接收路径和查询参数 - 使用curl或Postman测试所有接口
- 在README.md中记录测试命令和输出结果
扩展挑战 :尝试使用@RequestParam(defaultValue = "false") boolean useVirtual参数,当useVirtual=true时通过Thread.ofVirtual().start()在虚拟线程中执行操作,对比虚拟线程和平台线程的执行效率。