Spring?Boot從3.x到4.0的分步升級(jí)保姆級(jí)實(shí)戰(zhàn)指南
前言
Spring Boot 4.0于2025年11月20日正式發(fā)布,是繼2.x到3.x之后框架的又一次重大重構(gòu)。本次升級(jí)將單體自動(dòng)配置拆分為47個(gè)輕量模塊、原生集成JSpecify空安全校驗(yàn)、內(nèi)置API版本控制能力,同時(shí)基于Spring Framework 7.0打造,帶來了更優(yōu)的性能和開發(fā)體驗(yàn)。Spring Boot 3.5.x的支持將持續(xù)至2026年11月,為開發(fā)者預(yù)留了充足的遷移時(shí)間,而新特性帶來的性能提升和開發(fā)效率優(yōu)化,讓遷移具備極高的實(shí)際價(jià)值。
本文基于生產(chǎn)環(huán)境服務(wù)的遷移實(shí)踐,從版本前置升級(jí)、環(huán)境檢查、核心配置修改、空安全修復(fù)、API版本控制配置等方面,提供可落地的分步遷移指南,同時(shí)梳理遷移過程中的常見問題與解決方案,幫你平穩(wěn)完成從Spring Boot 3.5到4.0的升級(jí)。
一、Spring Boot 4.0 核心變更與升級(jí)價(jià)值
Spring Boot 4.0的核心更新圍繞模塊化、空安全、原生功能增強(qiáng)展開,最低要求Java 17(推薦Java 21 LTS),Kotlin項(xiàng)目需升級(jí)至2.2及以上版本,核心變更及升級(jí)帶來的實(shí)際價(jià)值如下:
1.1 核心變更
- 自動(dòng)配置模塊化:將原6.2MB的
spring-boot-autoconfigure單體JAR拆分為47個(gè)專屬輕量模塊,引入spring-boot-starter-web僅加載WebMVC配置,不再包含批處理、MongoDB等無(wú)關(guān)配置; - 空安全體系升級(jí):使用JSpecify 1.0替代原
org.springframework.lang的空注解,支持編譯期空安全校驗(yàn),提前規(guī)避NPE問題; - 原生API版本控制:無(wú)需自定義
RequestMappingHandlerMapping或路徑拼接,通過注解和配置即可實(shí)現(xiàn)Header/路徑式API版本控制; - 聲明式HTTP客戶端:內(nèi)置聲明式HTTP客戶端,無(wú)需依賴Feign等第三方庫(kù);
- 可觀測(cè)性增強(qiáng):集成Micrometer 2.0,支持SSL健康檢查,監(jiān)控能力更完善;
- 依賴與測(cè)試調(diào)整:移除
MockitoTestExecutionListener,需改用MockitoExtension;精簡(jiǎn)spring-boot-starter-parent結(jié)構(gòu);核心消息抽象遷移至spring-messaging模塊。
1.2 實(shí)際升級(jí)價(jià)值
基于生產(chǎn)服務(wù)的遷移實(shí)測(cè),Spring Boot 4.0相比3.5.x帶來了顯著的性能和開發(fā)體驗(yàn)提升:
- 鏡像體積減少19%:從387MB降至312MB,降低容器部署的存儲(chǔ)和網(wǎng)絡(luò)成本;
- 啟動(dòng)時(shí)間縮短33%:從4.2秒降至2.8秒,提升服務(wù)彈性擴(kuò)縮容效率;
- 消除冗余代碼:原生API版本控制可移除200行左右的自定義路由代碼;
- 提前規(guī)避BUG:編譯期空安全校驗(yàn)可發(fā)現(xiàn)潛在的空指針問題,減少生產(chǎn)環(huán)境故障;
- 依賴更簡(jiǎn)潔:模塊化的自動(dòng)配置讓依賴圖譜更清晰,減少無(wú)用依賴的加載。
二、遷移前置準(zhǔn)備
2.1 版本前置升級(jí):先升級(jí)至3.5.x最新版
禁止直接從3.3及以下版本跳級(jí)至4.0,需先升級(jí)到Spring Boot 3.5.x的最新版本(截至2025年12月為3.5.6),該步驟可提前暴露棄用警告,確保依賴的兼容性。
Maven配置修改
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.5.6</version> </parent>
Gradle配置修改
plugins {
id 'org.springframework.boot' version '3.5.6'
}升級(jí)后執(zhí)行測(cè)試,修復(fù)所有失敗用例:
# Maven ./mvnw clean test # Gradle ./gradlew clean test
關(guān)鍵修復(fù):3.4開始棄用MockitoTestExecutionListener,4.0直接移除,若測(cè)試類使用@Mock/@Captor但未引入MockitoExtension,會(huì)出現(xiàn)Mock對(duì)象為null的問題,需在測(cè)試類添加:
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class MyServiceTest {
@Mock
private MyRepository repo;
// 測(cè)試邏輯
}
2.2 檢查并升級(jí)Java/Kotlin版本
Spring Boot 4.0要求Java 17及以上(推薦Java 21 LTS),Kotlin項(xiàng)目需Kotlin 2.2及以上,先檢查當(dāng)前版本:
java -version
Java 21 安裝(主流系統(tǒng))
- macOS(Homebrew):
brew install openjdk@21
- Ubuntu:
sudo apt update sudo apt install openjdk-21-jdk
構(gòu)建文件中指定Java版本
- Maven(pom.xml):
<properties> <java.version>21</java.version> </properties>
- Gradle(build.gradle):
java { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 }
Kotlin版本升級(jí)(pom.xml)
<kotlin.version>2.2.0</kotlin.version>
修改后重新構(gòu)建并測(cè)試,確保基礎(chǔ)環(huán)境無(wú)問題。
三、正式升級(jí)至Spring Boot 4.0.0
完成前置準(zhǔn)備后,將Spring Boot版本正式修改為4.0.0,這一步是遷移的核心,會(huì)出現(xiàn)依賴和編譯相關(guān)的錯(cuò)誤,需逐一修復(fù)。
3.1 修改構(gòu)建文件版本
Maven
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>4.0.0</version> </parent>
Gradle
plugins {
id 'org.springframework.boot' version '4.0.0'
}3.2 執(zhí)行構(gòu)建并修復(fù)依賴缺失問題
# Maven ./mvnw clean package # Gradle ./gradlew clean build
最常見錯(cuò)誤:模塊化拆分后,直接導(dǎo)入自動(dòng)配置類但未引入對(duì)應(yīng)starter的,會(huì)出現(xiàn)類缺失,需添加專屬starter依賴。
示例:使用Spring Data MongoDB需添加:
<!-- 非響應(yīng)式 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <!-- 響應(yīng)式 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId> </dependency>
若未使用starter,需手動(dòng)添加對(duì)應(yīng)的自動(dòng)配置模塊(模塊列表參考Spring Boot 4.0官方遷移指南),例如使用TestRestTemplate需添加:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure-web</artifactId> </dependency>
四、修復(fù)JSpecify空安全警告
Spring Boot 4.0全面采用JSpecify 1.0的空注解(org.jspecify.annotations),替代原Spring的空注解(org.springframework.lang),支持編譯期空安全校驗(yàn),是本次升級(jí)的核心重點(diǎn)之一。
4.1 添加JSpecify依賴
<dependency> <groupId>org.jspecify</groupId> <artifactId>jspecify</artifactId> <version>1.0.0</version> </dependency>
4.2 開啟包級(jí)別的空安全標(biāo)記
創(chuàng)建package-info.java文件,標(biāo)記當(dāng)前包為默認(rèn)非空,僅顯式標(biāo)注@Nullable的對(duì)象可為空,實(shí)現(xiàn)全局空安全約束:
@NullMarked package com.example.myapp; import org.jspecify.annotations.NullMarked;
4.3 修復(fù)具體的空安全警告
添加依賴和標(biāo)記后,IDEA 2025.3+/Eclipse(Spring Tools)會(huì)在編譯期提示空安全警告,核心修復(fù)場(chǎng)景為未處理可空對(duì)象的空值情況。
典型場(chǎng)景:倉(cāng)庫(kù)查詢結(jié)果未判空
原代碼(有警告):
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// findById返回@Nullable User/Optional<User>,直接返回會(huì)觸發(fā)警告
return userRepository.findById(id);
}
修復(fù)后代碼:
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// 方式1:Optional判空
return userRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
// 方式2:直接判空
/*
User user = userRepository.findById(id);
if (user == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
return user;
*/
}
4.4 (可選)構(gòu)建期強(qiáng)制空安全校驗(yàn)
若需要在CI/構(gòu)建階段強(qiáng)制校驗(yàn)空安全,可集成NullAway,拒絕空安全違規(guī)的代碼構(gòu)建(需Java 21+),Maven配置示例:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-XDaddTypeAnnotationsToSymbol=true</arg>
<arg>-Xplugin:NullAway</arg>
</compilerArgs>
<annotationProcessorPaths>
<path>
<groupId>com.uber.nullaway</groupId>
<artifactId>nullaway</artifactId>
<version>0.10.12</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>執(zhí)行mvn compile,若存在空安全違規(guī),構(gòu)建會(huì)直接失敗。
五、配置原生API版本控制
Spring Boot 4.0內(nèi)置API版本控制能力,無(wú)需自定義代碼,支持Header式和路徑式兩種方式,徹底替代傳統(tǒng)的路徑拼接/自定義處理器方案。
5.1 核心配置:選擇版本控制方式
在application.properties/application.yml中配置版本控制的核心規(guī)則,二選一即可。
方式1:Header式版本控制(推薦)
通過請(qǐng)求頭傳遞API版本,保持URL整潔,適合內(nèi)部服務(wù)/前后端分離項(xiàng)目:
# 自定義頭名稱為API-Version spring.mvc.apiversion.use.header=API-Version
方式2:路徑式版本控制
通過URL路徑段傳遞API版本,適合瀏覽器端/無(wú)請(qǐng)求頭控制的場(chǎng)景:
# 數(shù)字1表示版本為URL的第2個(gè)路徑段(索引從0開始) spring.mvc.apiversion.use.path-segment=1 # 示例:/api/v1.2/users → 版本為v1.2
5.2 接口中添加版本注解
在@GetMapping/@PostMapping等注解中通過version屬性指定接口版本,支持多版本接口共存。
Header式版本控制示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
@RequestMapping("/api/users")
public class UserController {
// 1.0版本接口:返回舊版VO
@GetMapping(value = "/{id}", version = "1.0")
public UserV1 getUserV1(@PathVariable Long id) {
return userService.getV1User(id);
}
// 1.1版本接口:返回新版VO(含擴(kuò)展字段)
@GetMapping(value = "/{id}", version = "1.1")
public UserV2 getUserV2(@PathVariable Long id) {
return userService.getV2User(id);
}
}
客戶端調(diào)用示例(curl)
# 調(diào)用1.0版本 curl -H "API-Version: 1.0" http://localhost:8080/api/users/1 # 調(diào)用1.1版本 curl -H "API-Version: 1.1" http://localhost:8080/api/users/1
5.3 高級(jí)用法:基線版本匹配
使用1.0+表示匹配1.0及以上所有版本,避免未變更接口的版本注解重復(fù)編寫:
// 匹配1.0、1.1、1.2等版本,除非有更具體的版本接口
@GetMapping(value = "/list", version = "1.0+")
public List<UserV1> getUserList() {
return userService.listV1Users();
}
5.4 服務(wù)間調(diào)用:API版本自動(dòng)注入
使用RestClient調(diào)用其他服務(wù)時(shí),可配置版本注入器,自動(dòng)添加版本頭,無(wú)需手動(dòng)設(shè)置:
import org.springframework.web.client.RestClient;
import org.springframework.web.servlet.mvc.method.annotation.ApiVersionInserter;
RestClient client = RestClient.builder()
.baseUrl("http://localhost:8080")
// 配置Header式版本注入
.apiVersionInserter(ApiVersionInserter.useHeader("API-Version"))
.build();
// 調(diào)用時(shí)指定版本,自動(dòng)添加API-Version:1.1頭
UserV2 user = client.get()
.uri("/api/users/1")
.apiVersion("1.1")
.retrieve()
.body(UserV2.class);
六、替換所有棄用的API
Spring Boot 4.0移除了大量棄用的類和注解,需在IDE中檢查刪除線標(biāo)注的棄用代碼,替換為官方推薦的替代方案,核心替換點(diǎn)如下:
6.1 空注解替換
// 舊:Spring原生注解 import org.springframework.lang.Nullable; // 新:JSpecify注解 import org.jspecify.annotations.Nullable;
6.2 Mock相關(guān)注解替換
// 舊 import org.springframework.boot.test.mock.mockito.MockBean; // 新(3.5+推薦) import org.springframework.test.context.bean.override.mockito.MockitoBean; // 或直接使用@Mock + MockitoExtension(推薦)
6.3 核心類包遷移
核心消息抽象從spring-context遷移至spring-messaging,若使用相關(guān)類,需調(diào)整導(dǎo)入包(IDE會(huì)自動(dòng)提示)。
七、遷移過程中的常見問題與解決方案
結(jié)合生產(chǎn)服務(wù)的遷移實(shí)踐,梳理6類最常見的問題及快速解決方案,覆蓋依賴、測(cè)試、配置等核心場(chǎng)景。
問題1:TestRestTemplate 無(wú)法解析
錯(cuò)誤:Cannot resolve symbol 'TestRestTemplate'
解決方案:添加spring-boot-starter-test依賴(測(cè)試環(huán)境)或手動(dòng)添加web自動(dòng)配置模塊:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
問題2:MongoTemplate/RedisTemplate 注入失敗
錯(cuò)誤:No qualifying bean of type 'org.springframework.data.mongodb.core.MongoTemplate'
解決方案:模塊化后,需添加對(duì)應(yīng)的數(shù)據(jù)庫(kù)starter,而非僅依賴核心包:
<!-- MongoDB --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
問題3:@Mock 字段為null,測(cè)試報(bào)NPE
錯(cuò)誤:NullPointerException(Mock對(duì)象未初始化)
解決方案:測(cè)試類添加@ExtendWith(MockitoExtension.class),移除棄用的@RunWith(MockitoJUnitRunner.class)。
問題4:JSpecify 注解無(wú)提示,IDEA不識(shí)別
解決方案:
- 升級(jí)IDEA至2025.3及以上版本;
- 項(xiàng)目SDK設(shè)置為Java 21;
- 確保添加了JSpecify 1.0.0依賴;
- IDEA中開啟
File > Settings > Build, Execution, Deployment > Compiler > Java Compiler的注解處理。
問題5:路徑式版本控制返回404
錯(cuò)誤:配置路徑式版本控制后,所有請(qǐng)求返回404
解決方案:@RequestMapping中必須包含{version}路徑變量,Spring通過該變量提取版本:
// 正確
@RequestMapping("/api/{version}/users")
// 錯(cuò)誤
@RequestMapping("/api/users")問題6:Maven依賴沖突,Spring Framework版本低于7.0
錯(cuò)誤:Dependency convergence error(依賴樹中存在Spring Framework <7.0的版本)
解決方案:查看依賴樹,找到引入低版本Spring的依賴并升級(jí)/排除:
# 查看Maven依賴樹
./mvnw dependency:tree
# 排除低版本依賴示例
<dependency>
<groupId>com.example</groupId>
<artifactId>old-dependency</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>八、Spring Boot 3.5 vs 4.0 核心指標(biāo)對(duì)比
基于實(shí)際生產(chǎn)服務(wù)的遷移實(shí)測(cè),核心指標(biāo)對(duì)比如下,直觀體現(xiàn)升級(jí)的價(jià)值:
| 指標(biāo) | Spring Boot 3.5.6 | Spring Boot 4.0.0 | 變化 |
|---|---|---|---|
| 容器鏡像體積 | 387 MB | 312 MB | 減少19% |
| 服務(wù)啟動(dòng)時(shí)間 | 4.2s | 2.8s | 縮短33% |
| 空安全校驗(yàn) | 無(wú) | 編譯期警告/強(qiáng)制 | 提前規(guī)避NPE |
| API版本控制 | 需自定義代碼 | 框架原生支持 | 移除200行代碼 |
| 自動(dòng)配置結(jié)構(gòu) | 1個(gè)單體JAR | 47個(gè)輕量模塊 | 依賴更簡(jiǎn)潔 |
| Java基線 | 17(可選21) | 17(推薦21) | 一致 |
| Kotlin基線 | 1.9 | 2.2 | 強(qiáng)制升級(jí) |
| 測(cè)試框架 | 支持舊版Mockito | 僅支持MockitoExtension | 規(guī)范測(cè)試寫法 |
九、后續(xù)規(guī)劃與生態(tài)展望
9.1 版本支持與后續(xù)升級(jí)
- Spring Boot 3.5.x:官方支持至2026年11月,可根據(jù)業(yè)務(wù)節(jié)奏擇機(jī)遷移;
- Spring Boot 4.0.1:2025年12月9日發(fā)布,僅修復(fù)小BUG,無(wú)破壞性變更,可直接升級(jí);
- Spring Boot 4.1:預(yù)計(jì)2026年Q2發(fā)布,重點(diǎn)增強(qiáng)響應(yīng)式能力、進(jìn)一步模塊化,同時(shí)優(yōu)化GraalVM原生鏡像構(gòu)建,降低無(wú)服務(wù)應(yīng)用的冷啟動(dòng)時(shí)間。
9.2 生態(tài)兼容注意事項(xiàng)
目前部分第三方庫(kù)尚未完成Spring Framework 7.0的適配,遷移前需檢查核心依賴的兼容性:
- 優(yōu)先使用Spring官方生態(tài)的依賴,兼容性最高;
- 自定義starter/內(nèi)部庫(kù)需提前完成4.0適配;
- 日志、監(jiān)控等通用庫(kù),優(yōu)先升級(jí)至最新版本。
9.3 遷移后的最佳實(shí)踐
- 全面推行空安全編碼:基于JSpecify規(guī)范,所有新代碼添加空注解,逐步改造舊代碼;
- 基于原生API版本控制:統(tǒng)一團(tuán)隊(duì)的API版本規(guī)范,避免自定義方案的碎片化;
- 精簡(jiǎn)依賴:移除無(wú)用的starter,利用模塊化優(yōu)勢(shì)進(jìn)一步降低鏡像體積;
- 開啟構(gòu)建期空安全強(qiáng)制校驗(yàn):在CI/CD流水線中集成NullAway,拒絕空安全違規(guī)代碼合并。
十、總結(jié)
Spring Boot 4.0是一次高性能、高安全性、高開發(fā)效率的重大升級(jí),模塊化的自動(dòng)配置、原生的空安全校驗(yàn)、內(nèi)置的API版本控制三大核心特性,不僅帶來了顯著的性能提升,更從框架層面規(guī)范了開發(fā)流程,提前規(guī)避生產(chǎn)環(huán)境的常見BUG。
本次遷移的核心原則是分步升級(jí)、前置修復(fù):先升級(jí)至3.5.x最新版,修復(fù)棄用警告,再檢查并升級(jí)基礎(chǔ)環(huán)境,最后正式升級(jí)至4.0并修復(fù)依賴、編譯問題。從實(shí)際實(shí)踐來看,無(wú)復(fù)雜自定義配置的服務(wù),90分鐘內(nèi)可完成遷移;存在自定義自動(dòng)配置/多依賴的服務(wù),約4小時(shí)可完成,整體遷移成本可控。
對(duì)于擁有公共API的服務(wù),原生API版本控制特性足以成為遷移的核心理由;對(duì)于追求性能的容器/無(wú)服務(wù)部署場(chǎng)景,19%的鏡像體積減少+33%的啟動(dòng)時(shí)間縮短能直接降低運(yùn)行成本;而空安全校驗(yàn)則是長(zhǎng)期的價(jià)值,能持續(xù)減少生產(chǎn)環(huán)境的空指針故障。
到此這篇關(guān)于Spring Boot從3.x到4.0的分步升級(jí)保姆級(jí)實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring Boot3.x升級(jí)4.0內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java使用dom4j解析xml配置文件實(shí)現(xiàn)抽象工廠反射示例
本文主要介紹了java使用dom4j讀取配置文件實(shí)現(xiàn)抽象工廠和反射的示例,在Java中也可以同Donet一樣,將差異配置在配置文件里面。另外,我們采用下面的方式實(shí)現(xiàn),將會(huì)更加便捷2014-01-01
IDEA2021.2永久激活碼最新超詳細(xì)(激活到2099)
這篇文章主要介紹了IDEA2021.2永久激活碼,是idea2021版最新激活方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
SpringBoot循環(huán)依賴全場(chǎng)景解析與終極解決方案
這篇文章主要為大家詳細(xì)介紹了SpringBoot循環(huán)依賴全場(chǎng)景解析與終極解決方案,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-06-06
idea中創(chuàng)建多module的maven工程的方法
這篇文章主要介紹了idea中創(chuàng)建多module的maven工程的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10
Java實(shí)現(xiàn)中序表達(dá)式的實(shí)例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)中序表達(dá)式的實(shí)例代碼,需要的朋友可以參考下2018-08-08

