系列定位:基于 Spring Boot 4.1.0 GA 源码,以「新特性解读 + 源码佐证 + 实战落地」为主线,带你深度理解 Spring Boot 4 的核心变革。
本文目标:30 分钟掌握从 Boot 3.x 升级到 4.x 的全量迁移要点,包含每项变更的影响面分析、代码改写示例、以及一份可直接对照执行的 Migration Checklist。
📢 前言:升级不可怕,可怕的是不知道要改什么
兄弟们,升级 Spring Boot 大版本,最让人焦虑的是什么?
不是"写新代码",而是**"改旧代码"**——你到底要改哪些地方?改了会不会引发连锁故障?线上跑着的服务会不会突然挂掉?
😫 过来人的痛:当年 Boot 2→3 那波
javax→jakarta全量包名地震,多少人通宵排查ClassNotFoundException?多少第三方库一夜之间全部报红?
好消息是,Spring Boot 4 的升级路径比 Boot 2→3 平滑得多。没有再来一次包名级别的全量地震(那个已经在 Boot 3 做完了),但仍有一批"必须改"和"建议改"的要点。
本文逐一拆解 10 大类升级变更项,每项都基于 Spring Boot 4.1.0 源码验证,并标注影响等级。先看这张等级表,心里有数:
| 影响等级 | 含义 | 你需要做什么 |
|---|---|---|
| 🔴 必须改 | 不改编译/启动失败 | 立刻改,没商量 |
| 🟡 建议改 | 旧方式仍可用但已被弃用,未来版本将移除 | 有空就改,别拖 |
| 🟢 零成本收益 | 新增能力,不需要改代码就能享受 | 白嫖,爽 |
💡 建议收藏本文,升级时对照 Checklist 逐项打勾,不漏一个坑。
🛠️ 先认识一个"救命"模块:spring-boot-properties-migrator
在逐项讲解前,先给大家介绍一个升级路上的"救命稻草"——spring-boot-properties-migrator。这个模块能帮你自动检测和迁移已弃用的配置项,省去大量人工排查的功夫。
源码切入点
源码位置:core/spring-boot-properties-migrator/
这个模块的核心类是 PropertiesMigrationListener,它实现了 ApplicationListener<SpringApplicationEvent>,在应用启动的两个关键时刻介入:
// PropertiesMigrationListener.java 关键逻辑
@Override
public void onApplicationEvent(SpringApplicationEvent event) {
if (event instanceof ApplicationPreparedEvent preparedEvent) {
onApplicationPreparedEvent(preparedEvent); // ① 环境准备后扫描配置
}
if (event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent) {
logLegacyPropertiesReport(); // ② 启动完成/失败时输出报告
}
}
它的工作流程如下:
sequenceDiagram
participant App as 应用启动
participant Listener as PropertiesMigrationListener
participant Repo as ConfigurationMetadataRepository
participant Reporter as PropertiesMigrationReporter
participant Env as ConfigurableEnvironment
App->>Listener: ApplicationPreparedEvent
Listener->>Repo: 加载所有 META-INF/spring-configuration-metadata.json
Repo-->>Listener: 返回所有配置元数据
Listener->>Reporter: 传入元数据 + Environment
Reporter->>Reporter: 遍历所有 PropertySource
Note over Reporter: 匹配 @Deprecated 标记的配置项
Reporter->>Env: 自动重命名兼容的旧属性
Reporter-->>Listener: 返回 MigrationReport
App->>Listener: ApplicationReadyEvent
Listener->>Listener: logLegacyPropertiesReport()
Note over Listener: 输出 WARN/ERROR 级别迁移报告
怎么用?一行依赖搞定
<!-- Maven -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
// Gradle
runtimeOnly("org.springframework.boot:spring-boot-properties-migrator")
启动应用后,如果配置文件中有已弃用的属性,控制台会直接告诉你该改成什么:
WARN [PropertiesMigrationListener] -
The use of configuration keys that have been renamed was found in the environment:
Property source 'applicationConfig: [classpath:/application.yml]':
Key: server.servlet.path
Line: 3
Replacement: spring.mvc.servlet.path
💡 关键特性:对于类型兼容的配置项(如同类型的重命名、
Long/Integer→Duration的自动转换等),PropertiesMigrationReporter会自动迁移——自动用新属性名创建 PropertySource 并注入 Environment,旧属性名依然可用但会打印 WARN 级别警告。类型不兼容的(如String→Map)无法自动迁移,会在报告中以 ERROR 级别提示。简单说:能自动改的它帮你改,不能自动改的它告诉你怎么改。 升级必备,没有之一。
🔥 10 大类升级变更逐项指南(硬核预警)
接下来进入正文,每一项都附带源码证据 + 改写示例,大家可以对照自己的项目逐项排查。
变更 1:JDK 版本基线 — JDK 17 硬性要求,JDK 25 强烈推荐 🔴
⚡ 一句话总结:JDK 17 是底线,低于这个版本连编译都过不了。推荐直接上 JDK 25,能白嫖一堆新特性。
源码证据:starter/spring-boot-starter-parent/build.gradle
delegate."java.version"('17')
Spring Boot 4 的 JDK 17 是硬性编译基线,不可降级。同时,官方强烈推荐使用 JDK 25,以充分利用:
| JDK 特性 | 最低版本 | 在 Spring Boot 4 中的应用 |
|---|---|---|
| 虚拟线程 GA | JDK 21 | spring.threads.virtual.enabled=true 的前置条件 |
| Record 类 | JDK 16 (GA 17) | 配置属性绑定、DTO 简化 |
| Sealed Class | JDK 17 | 模块化自动配置的类型层级 |
| Pattern Matching for switch | JDK 21 | 框架内部条件判断简化 |
| Scoped Values | JDK 21 (GA 25) | 替代 ThreadLocal 的上下文传递(4.1 增强) |
| Stream Gatherers | JDK 24 | 框架内部流处理优化 |
源码证据:Threading.java 中的 JDK 版本判断
VIRTUAL {
@Override
public boolean isActive(Environment environment) {
return environment.getProperty("spring.threads.virtual.enabled",
boolean.class, false)
&& JavaVersion.getJavaVersion()
.isEqualOrNewerThan(JavaVersion.TWENTY_ONE); // 虚拟线程需要 JDK 21+
}
};
升级操作:
# 检查当前 JDK 版本
java -version
# 推荐:安装 JDK 25(以 SDKMAN 为例)
sdk install java 25.0.1-tem
sdk use java 25.0.1-tem
变更 2:jakarta.* 包名 — 继续深化,Servlet 6.1 全面就绪 🔴
⚡ 一句话总结:如果你已经从 Boot 2 升到了 Boot 3,这节基本可以跳过。如果还在用
javax,赶紧改!
⚠️ 如果项目已从 Boot 2 升级到 Boot 3,
javax.*→jakarta.*的迁移应该已完成。本节主要针对仍在使用 javax 依赖的遗留项目。
Spring Boot 4 底层使用 Tomcat 11.0.22(源码 gradle.properties 第 27 行):
tomcatVersion=11.0.22
Tomcat 11 实现了 Jakarta Servlet 6.1 规范,对 javax.servlet.* 零容忍——任何残留都会导致 ClassNotFoundException。
需要确认的包名迁移清单:
| 旧包名 (javax) | 新包名 (jakarta) | 涉及场景 |
|---|---|---|
javax.servlet.* | jakarta.servlet.* | Filter、Servlet、Listener |
javax.persistence.* | jakarta.persistence.* | JPA Entity、Repository |
javax.validation.* | jakarta.validation.* | @Valid、@NotNull 等校验注解 |
javax.transaction.* | jakarta.transaction.* | JTA 事务管理(UserTransaction、TransactionManager) |
javax.annotation.* | jakarta.annotation.* | @PostConstruct、@PreDestroy、@Resource |
javax.mail.* | jakarta.mail.* | 邮件发送 |
javax.json.* | jakarta.json.* | JSON 处理 |
一行命令快速排查(在项目根目录执行):
# 检查是否还有 javax 包引用
grep -r "import javax\." --include="*.java" src/ | grep -v "javax.annotation.processing"
# 检查 Maven/Gradle 依赖中是否还有 javax 坐标
mvn dependency:tree | grep "javax\." # Maven
gradle dependencies | grep "javax\." # Gradle
如果仍有 javax 依赖的第三方库,可以使用 jakarta-transformer 工具进行字节码级别的自动转换:
<!-- Maven plugin: 自动转换 javax → jakarta -->
<plugin>
<groupId>org.eclipse.transformer</groupId>
<artifactId>transformer-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<goals><goal>transform</goal></goals>
</execution>
</executions>
</plugin>
变更 3:Jackson 2.x → 3.x — 核心类库包名全变,但注解原地不动 🔴🟡
⚡ 一句话总结:这是整个升级中代码改动量最大的一块!核心类包名从
com.fasterxml.jackson变成tools.jackson,但注解包名不变。别搞混了!
这是 Boot 4 升级中影响面最大的代码变更。Spring Boot 4 默认使用 Jackson 3(tools.jackson.* 包名),Jackson 2 仅作为过渡支持。
源码证据:gradle.properties
jackson2Version=2.21.4 # 遗留支持(已弃用)
jacksonVersion=3.1.4 # 主力版本
🔑 核心变化:类库包名变了,但注解包名不变
// ❌ Jackson 2 核心类(Spring Boot 3.x 时代)
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
// ✅ Jackson 3 核心类(Spring Boot 4.x 默认)
import tools.jackson.core.JsonFactory;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
// ✅ 注解包名保持不变!(向下兼容)
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
🚨 划重点:
com.fasterxml.jackson.annotation.*注解包名不需要改!只有core、databind、dataformat三个包名要换。搞混了会多改一堆不该改的代码。
整个 spring-boot-jackson2 模块已弃用
源码证据:module/spring-boot-jackson2/ 中所有核心类
// JsonComponent.java 第 61-68 行
@Deprecated(since = "4.0.0", forRemoval = true)
public @interface JsonComponent { ... }
// JsonObjectSerializer.java 第 35-38 行
@Deprecated(since = "4.0.0", forRemoval = true)
public abstract class JsonObjectSerializer<T> { ... }
// Jackson2BackgroundPreinitializer.java 第 27-29 行
@Deprecated(since = "4.0.0", forRemoval = true)
public class Jackson2BackgroundPreinitializer { ... }
弃用时间线:Jackson 2 支持将在 Spring Boot 4.3.0 中彻底移除。也就是说,你有 4.0 → 4.3 的过渡窗口期,但别拖到最后。
必须修改的代码
// ❌ Boot 3.x:使用 Jackson2ObjectMapperBuilder
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL);
}
// ✅ Boot 4.x:使用 JsonMapper.builder() + JsonMapperBuilderCustomizer
@Bean
public JsonMapperBuilderCustomizer customizer() {
return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL);
}
Spring Boot 4.1 新增的 Jackson 配置(spring.jackson.factory.*)
这个新配置可以帮你防御 JSON 炸弹攻击,之前需要手动写代码拦截的,现在配置文件搞定:
spring:
jackson:
factory:
constraints:
read:
max-nesting-depth: 500 # JSON 最大嵌套深度
max-document-length: -1 # 最大文档长度(-1 不限)
max-string-length: 100000000 # 最大字符串长度
max-number-length: 1000 # 最大数字长度
max-name-length: 50000 # 最大属性名长度
write:
max-nesting-depth: 500 # 序列化最大嵌套深度
批量替换脚本(懒人福音)
# 查找所有使用 Jackson 2 核心包名的 Java 文件
grep -r "import com\.fasterxml\.jackson\.\(core\|databind\|dataformat\)" --include="*.java" src/
# 批量替换(macOS 使用 sed -i '')
find src/ -name "*.java" -exec sed -i '' \
-e 's/import com\.fasterxml\.jackson\.core\./import tools.jackson.core./g' \
-e 's/import com\.fasterxml\.jackson\.databind\./import tools.jackson.databind./g' \
-e 's/import com\.fasterxml\.jackson\.dataformat\./import tools.jackson.dataformat./g' {} +
# ⚠️ 注意:不要替换注解包名!
# com.fasterxml.jackson.annotation.* 保持不变
变更 4:Undertow 被彻底移除 — 必须切换 Web 容器 🔴
⚡ 一句话总结:Undertow 在 Boot 4 中连源码都没了。如果你之前用的 Undertow,必须切到 Tomcat 或 Jetty。
在 Spring Boot 4.1.0 的源码中,没有任何 Undertow 相关文件:
$ find . -name "*undertow*" 2>/dev/null
# 无结果 —— Undertow 已被完全移除
在 starter/ 目录下,只有以下 Web 容器 Starter:
spring-boot-starter-tomcat ← 默认(Servlet 容器)
spring-boot-starter-jetty ← 备选(Servlet 容器)
spring-boot-starter-reactor-netty ← WebFlux 默认(响应式容器)
如果你之前在 Boot 3.x 中使用 Undertow
Maven 切换示例:
<!-- ❌ Boot 3.x:使用 Undertow -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- ✅ Boot 4.x:切换为 Tomcat(默认,如果用了 spring-boot-starter-web 则无需额外添加) -->
<!-- Tomcat 已包含在 spring-boot-starter-web 的传递依赖中 -->
<!-- 或切换为 Jetty -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Gradle 切换示例:
// ❌ Boot 3.x
implementation("org.springframework.boot:spring-boot-starter-undertow")
// ✅ Boot 4.x — 排除默认 Tomcat,使用 Jetty
implementation("org.springframework.boot:spring-boot-starter-web") {
exclude(module = "spring-boot-starter-tomcat")
}
implementation("org.springframework.boot:spring-boot-starter-jetty")
Undertow 特有配置需要迁移:
| Undertow 配置 (已失效) | 对应 Tomcat/Jetty 配置 |
|---|---|
server.undertow.* | 迁移到 server.tomcat.* 或 server.jetty.* |
server.undertow.accesslog.* | server.tomcat.accesslog.* |
Undertow 自定义 UndertowBuilderCustomizer | TomcatServletWebServerFactoryCustomizer 或 JettyServletWebServerFactoryCustomizer |
变更 5:AntPathMatcher 弃用 — 统一使用 PathPatternParser 🔴
⚡ 一句话总结:
AntPathMatcher被弃用了,将在 4.2.0 移除。如果你的项目用了 Swagger/SpringFox,这里要特别注意!
源码证据:WebMvcProperties.java
public enum MatchingStrategy {
/**
* @deprecated since 4.0.0 for removal in 4.2.0 in favor of
* {@link #PATH_PATTERN_PARSER}
*/
@Deprecated(since = "4.0.0", forRemoval = true)
ANT_PATH_MATCHER,
PATH_PATTERN_PARSER
}
Spring Boot 4 统一使用 PathPatternParser 作为 URL 路径匹配策略,AntPathMatcher 已被弃用,将在 4.2.0 中移除。
受影响的配置:
# ❌ Boot 3.x:显式指定 AntPathMatcher
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
# ✅ Boot 4.x:必须切换(或删除,默认就是 PATH_PATTERN_PARSER)
spring:
mvc:
pathmatch:
matching-strategy: path_pattern_parser
如果你的代码中有自定义 AntPathMatcher:
// ❌ Boot 3.x
@Bean
public AntPathMatcher antPathMatcher() {
return new AntPathMatcher();
}
// ✅ Boot 4.x:改用 PathPatternParser
@Bean
public PathPatternParser pathPatternParser() {
PathPatternParser parser = new PathPatternParser();
parser.setCaseSensitive(false);
return parser;
}
⚠️ 特别注意:如果项目中使用了 Swagger/SpringFox,它依赖 AntPathMatcher 解析路径模式。SpringFox 已停止维护,建议迁移到 SpringDoc OpenAPI(从 v2.8+ 开始支持 PathPatternParser)。
这也是很多人升级时踩的坑——SpringFox 不兼容,必须换 SpringDoc。
变更 6:EnvironmentPostProcessor 包名迁移 🔴
⚡ 一句话总结:接口还是那个接口,就是从
.env子包挪到了根包,改个 import 就行。
源码证据:core/spring-boot/src/main/java/org/springframework/boot/env/EnvironmentPostProcessor.java
/**
* @deprecated since 4.0.0 for removal in 4.2.0 in favor of
* {@link org.springframework.boot.EnvironmentPostProcessor}
*/
@FunctionalInterface
@Deprecated(since = "4.0.0", forRemoval = true)
public interface EnvironmentPostProcessor {
// 旧接口,位于 org.springframework.boot.env 包
}
Spring Boot 4 将 EnvironmentPostProcessor 从 org.springframework.boot.env 包提升到 org.springframework.boot 包:
// ❌ Boot 3.x
import org.springframework.boot.env.EnvironmentPostProcessor;
// ✅ Boot 4.x
import org.springframework.boot.EnvironmentPostProcessor;
新的 EnvironmentPostProcessor 接口功能与旧接口基本一致,核心差异在于包名和构造器参数支持:
- 包名从
org.springframework.boot.env提升到org.springframework.boot - 构造器可以接收
DeferredLogFactory(延迟日志工厂)和ConfigurableBootstrapContext(可配置的启动上下文) - 排序方式:实现
Ordered接口或标注@Order注解(与旧接口相同)
变更 7:RestTemplateBuilder.rootUri() 重命名为 baseUri() 🟡
⚡ 一句话总结:方法名从
rootUri改成了baseUri,语义更清晰。RestTemplate本身没被弃用,别慌。
源码证据:RestTemplateBuilder.java
/**
* @deprecated since 4.1.0 for removal in 4.3.0 in favor of {@link #baseUri(String)}
*/
@Deprecated(forRemoval = true, since = "4.1.0")
public RestTemplateBuilder rootUri(@Nullable String rootUri) {
// ...
}
// ❌ Boot 4.0.x(4.1.0 中弃用)
RestTemplate restTemplate = new RestTemplateBuilder()
.rootUri("http://api.example.com")
.build();
// ✅ Boot 4.1.0+
RestTemplate restTemplate = new RestTemplateBuilder()
.baseUri("http://api.example.com")
.build();
📝 注意:
RestTemplate本身并未被弃用,Spring Boot 4 仍然完全支持。但官方推荐新项目使用RestClient(同步)或WebClient(响应式)。RestTemplate处于"维护模式"——不新增功能,但会继续修复 Bug。
变更 8:SessionProperties.determineTimeout() 弃用 🟡
⚡ 一句话总结:如果你直接调用了这个方法,改用
SessionTimeout机制。大部分项目不会直接用到。
源码证据:SessionProperties.java
/**
* @deprecated since 4.0.1 for removal in 4.2.0 in favor of {@link SessionTimeout}
*/
@Deprecated(since = "4.0.1", forRemoval = true)
public Duration determineTimeout(Supplier<Duration> fallbackTimeout) {
return (this.timeout != null) ? this.timeout : fallbackTimeout.get();
}
如果代码中直接调用了 sessionProperties.determineTimeout(...),需要改为使用 SessionTimeout 机制。
变更 9:Health 模块三大类弃用 🟡
⚡ 一句话总结:健康检查模块有三个类被弃用了,自定义了状态聚合逻辑的需要改。
源码证据:module/spring-boot-health/src/main/java/
// 以下三个类均 @Deprecated(since = "4.1.0", forRemoval = true)
@Deprecated(since = "4.1.0", forRemoval = true)
public class SimpleStatusAggregator { ... }
@Deprecated(since = "4.1.0", forRemoval = true)
public interface HttpCodeStatusMapper { ... }
@Deprecated(since = "4.1.0", forRemoval = true)
public class SimpleHttpCodeStatusMapper { ... }
如果你自定义了健康检查的状态聚合逻辑,需要使用新的 API 替代(Spring Boot 4.1 推荐使用 StatusAggregator 实现)。
变更 10:spring.factories 中 AutoConfiguration 键的彻底移除 🟡
⚡ 一句话总结:自动配置类的注册方式从
spring.factories彻底迁移到了.imports文件。有自定义 AutoConfiguration 的要注意。
Spring Boot 3.x 开始,自动配置类的注册方式从 spring.factories 中的 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键迁移到 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件。
Spring Boot 4 彻底完成了这个迁移。虽然 spring.factories 本身仍然用于其他 SPI(ApplicationContextInitializer、ApplicationListener、FailureAnalyzer 等),但自动配置类已不再从 spring.factories 读取。
源码证据:AutoConfigurationImportSelector.java 只读取 AutoConfiguration.imports
// 自动配置只从 .imports 文件加载
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
@Nullable AnnotationAttributes attributes) {
ImportCandidates importCandidates = ImportCandidates.load(
this.autoConfigurationAnnotation, getBeanClassLoader());
List<String> configurations = importCandidates.getCandidates();
Assert.state(!CollectionUtils.isEmpty(configurations),
"No auto configuration classes found in META-INF/spring/"
+ this.autoConfigurationAnnotation.getName() + ".imports.");
return configurations;
}
如果你的项目有自定义 AutoConfiguration,需要确认注册方式:
# ❌ Boot 2.x 方式:META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
# ✅ Boot 3.x/4.x 方式:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.MyAutoConfiguration
📊 影响面分级总结:一张图看懂你要改什么
💡 看图说话:如果你的项目用了 Tomcat + Jackson 注解(不直接用核心类)+ 没用 Undertow + 没用 SpringFox,那恭喜你,基本只需要改个 JDK 版本号和 Spring Boot 版本号就行了。
🌳 升级决策树:跟着走,不迷路
不知道自己项目要改哪些?跟着这棵决策树走一遍:
✅ 升级步骤 Checklist(建议收藏,对照打勾)
📌 使用方法:升级时逐项打勾,全部完成后可放心上线。
阶段一:环境准备
- JDK 升级到 17+(推荐 JDK 25)
java -version # 确认版本 - 更新 Spring Boot 版本号
<!-- Maven parent --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>4.1.0</version> </parent> - 更新 Gradle 插件
plugins { id 'org.springframework.boot' version '4.1.0' }
阶段二:依赖检查
- 移除 Undertow 依赖,切换为 Tomcat 或 Jetty
- 检查 Jackson 依赖
- 如果直接依赖了
jackson-databind等核心库,将com.fasterxml.jackson.core/databind/dataformat替换为tools.jackson.* - 如果使用了
spring-boot-starter-json(通过spring-boot-starter-web间接引入的情况最常见):无需改动,该 Starter 在 Boot 4 中已自动切换为依赖spring-boot-jackson(Jackson 3) - 注解依赖 (
com.fasterxml.jackson.annotation.*) 不需要改
- 如果直接依赖了
- 检查是否有
javax.*依赖残留mvn dependency:tree | grep "javax\." # Maven gradle dependencies | grep "javax\." # Gradle - 引入
spring-boot-properties-migrator(runtime scope,用于首次升级检测)
阶段三:代码修改
- 替换 Jackson 核心类导入(
com.fasterxml.jackson.core/databind/dataformat.*→tools.jackson.*) - 替换 Jackson2ObjectMapperBuilder → JsonMapper.builder()
// 旧 Jackson2ObjectMapperBuilder.json().build() // 新 JsonMapper.builder().build() - 检查所有
Jackson2ObjectMapperBuilderCustomizer→JsonMapperBuilderCustomizer - 将 Jackson 2 注解/基类迁移到 Jackson 3 对应物(类名有变化):
@JsonComponent→@JacksonComponentJsonObjectSerializer<T>→ObjectValueSerializer<T>JsonObjectDeserializer<T>→ObjectValueDeserializer<T>@JsonMixin→@JacksonMixinJsonComponentModule→JacksonComponentModule- 模块坐标从
spring-boot-jackson2→spring-boot-jackson
- 替换 EnvironmentPostProcessor 导入
// 旧 import org.springframework.boot.env.EnvironmentPostProcessor; // 新 import org.springframework.boot.EnvironmentPostProcessor; - 检查 RestTemplateBuilder 中的
.rootUri()→.baseUri() - 检查 AntPathMatcher 使用 → 替换为 PathPatternParser
- 如果使用 SpringFox → 迁移到 SpringDoc OpenAPI
- 检查自定义 SessionProperties.determineTimeout() 调用
- 检查自定义 Health 模块中是否使用了 SimpleStatusAggregator / HttpCodeStatusMapper / SimpleHttpCodeStatusMapper
阶段四:配置修改
- 移除
spring.mvc.pathmatch.matching-strategy=ant_path_matcher - 移除所有
server.undertow.*配置 - 确认
spring.factories中的自动配置已迁移到AutoConfiguration.imports
阶段五:启动验证
- 首次启动,观察
PropertiesMigrationListener输出的迁移报告 - 修复所有 WARN/ERROR 级别的配置迁移提示
- 全量运行单元测试和集成测试
- 验证 Jackson 序列化/反序列化行为一致
- 移除
spring-boot-properties-migrator依赖(迁移完成后)
🔗 Spring Cloud 兼容矩阵
升级 Boot 4 的同学,Spring Cloud 也得跟着升。别搞错版本对应关系:
| Spring Cloud 版本 | Spring Boot 版本 | Spring Framework | 状态 |
|---|---|---|---|
| 2025.0.x | 4.0.x / 4.1.x | 7.0.x | ✅ 兼容 |
| 2024.0.x | 3.4.x | 6.2.x | ❌ 不兼容 Boot 4 |
| 2023.0.x (Spring Cloud AWS 等) | 3.2.x / 3.3.x | 6.1.x | ❌ 不兼容 Boot 4 |
⚠️ 注意:Spring Cloud 2025.0.x 同样要求
jakarta.*命名空间,如果你同时使用了 Spring Cloud Netflix(Eureka、Hystrix 等已停止维护的项目),需要寻找替代方案或等待社区适配。
📝 总结:三句话讲清楚 Boot 3→4 升级
Spring Boot 3→4 的升级相比 2→3 友好得多。核心影响面集中在三个领域:
- Jackson 3 包名变更:核心类从
com.fasterxml.jackson→tools.jackson,这是最大的代码改动量 - Undertow 被移除:必须切换 Web 容器,但对于大多数已使用 Tomcat 的项目零影响
- 一批 API 的弃用与重命名:
spring-boot-properties-migrator能帮你自动发现和处理
建议的升级策略:先引入 migrator → 修正所有编译错误 → 启动验证 → 运行测试 → 移除 migrator,五步完成升级。
📚 系列导航:
- 第 01 篇:11 项重大变更全景解读 ✅
- 第 02 篇(本文):从 Spring Boot 3.x 到 4.0 最全升级避坑指南 ✅
- 第 03 篇(预告):Spring Boot 4 vs 3.x 全维度性能对比实测 🔜
- 第 04 篇(预告):告别十亿美元的错误——JSpecify 空安全完全实战指南 🔜
🔗 源码版本:Spring Boot 4.1.0 GA | Spring Framework 7.0.8 | JDK 21 基线 / 推荐 JDK 25
💬 写在最后
如果这篇文章帮你少踩了一个坑,点个赞再走呗👍
有什么升级过程中遇到的问题,欢迎在评论区交流,我会一一回复。
📮 关注我,第一时间获取后续 18 篇深度剖析文章。