Spring Boot 项目 JDK8 → JDK21 升级注意事项
基于 ai-knowledge 项目实际升级经验整理,适用于团队其他 Spring Boot 项目参考。
1. 环境要求
| 工具 | 最低版本 | 推荐版本 | 说明 |
|---|---|---|---|
| JDK | 21 | 21.0.11 (Oracle) | 本地路径 E:\software\Java\jdk-21.0.11 |
| Maven | 3.6.3 | 3.9.15 | Spring Boot 3.x 管理的插件要求 Maven ≥ 3.6.3,3.3.9 不兼容 |
| Spring Boot | 3.2.12 | 3.2.12 | 3.2.x 是首个官方支持 JDK21 LTS 的分支 |
⚠️ 重要:Maven 3.3.9 会报错
The plugin requires Maven version 3.6.3,必须升级 Maven。
2. 核心依赖版本清单
以下是经过本项目验证的兼容版本,直接使用可避免踩坑。
2.1 Spring Boot 父 POM
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.12</version>
<relativePath/>
</parent>
2.2 需要在 dependencyManagement 中强制覆盖的版本
Spring Boot 3.x 默认传递的某些依赖版本与 Spring 6.1 存在不兼容,必须在根 pom 中强制锁定:
<dependencyManagement>
<dependencies>
<!-- ✅ 强制锁定:mybatis-spring 2.1.x 与 Spring 6.1 的 MapperFactoryBean 不兼容
症状:Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
MyBatis-Plus 3.5.9 默认传递 2.1.2,必须覆盖为 3.0.4 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.4</version>
</dependency>
</dependencies>
</dependencyManagement>
2.3 完整依赖版本推荐表
| 依赖 GroupId:ArtifactId | 推荐版本 | 说明 |
|---|---|---|
org.projectlombok:lombok |
1.18.34 | 修复 JDK21 注解处理器问题,1.18.22 在 JDK21 下有警告 |
com.alibaba.fastjson2:fastjson2 |
2.0.53 | 修复 JDK21 反射相关问题,2.0.43 有潜在兼容风险 |
org.apache.commons:commons-lang3 |
3.14.0 | Spring Boot 3.2 管理版本 |
com.baomidou:mybatis-plus-boot-starter |
3.5.9 | ✅ 支持 Spring Boot 3.x;3.5.7 与 Spring 6.1 仍有兼容问题 |
com.baomidou:mybatis-plus-jsqlparser |
3.5.9 | ⚠️ 3.5.9 起分页拦截器从主包拆出,必须单独引入 |
org.mybatis:mybatis-spring |
3.0.4 | ✅ 专为 Spring 6.x 适配;需在 dependencyManagement 中强制覆盖 |
com.mysql:mysql-connector-j |
8.3.0 | ⚠️ Spring Boot 3.x 起 groupId/artifactId 变更(见下文) |
com.alibaba:druid-spring-boot-3-starter |
1.2.21 | ⚠️ Spring Boot 3.x 专用 artifact,旧版 druid-spring-boot-starter 不兼容 |
com.baomidou:dynamic-datasource-spring-boot3-starter |
4.3.0 | ⚠️ Spring Boot 3.x 专用 artifact,旧版 artifact 名不同 |
org.apache.httpcomponents:httpclient |
4.5.13 | 4.5.x 在 JDK21 下仍可用,无需强制升级到 5.x |
3. 根 pom.xml 改造
3.1 Java 版本属性
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
3.2 maven-compiler-plugin 配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>21</release>
<encoding>${project.build.sourceEncoding}</encoding>
<!-- ⚠️ 不要保留旧的 <compilerArguments><extdirs>lib</extdirs></compilerArguments>
该配置是 JDK8 遗留写法,与 --release 参数冲突,会导致:
Fatal error compiling: 无效的标记: --release -->
</configuration>
</plugin>
说明:使用
<release>21</release>而非<source>/<target>,--release参数同时控制 source、target 和 bootstrap classpath,更严格安全。
3.3 移除子模块中的冗余 compiler 配置
子模块 pom.xml 中如有以下旧式配置,直接删除,由根 pom 统一管理:
<!-- 删除这段 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
4. javax → jakarta 包名迁移
Spring Boot 3.x 基于 Jakarta EE 10,** 所有 javax.* 包已更名为 jakarta.***。
4.1 常见替换映射
| 旧包名(javax) | 新包名(jakarta) | 典型注解 / 类 |
|---|---|---|
javax.servlet.* |
jakarta.servlet.* |
HttpServletRequest, Filter |
javax.persistence.* |
jakarta.persistence.* |
@Entity, @Column, @Id |
javax.validation.* |
jakarta.validation.* |
@NotNull, @Valid |
javax.annotation.* |
jakarta.annotation.* |
@PostConstruct, @PreDestroy |
javax.transaction.* |
jakarta.transaction.* |
@Transactional(注意:Spring 的 @Transactional 不受影响) |
4.2 快速批量替换命令
在 IDEA 中:Ctrl+Shift+R(全局替换)逐条替换以上映射。
用 PowerShell 辅助检索:
# 检查项目中所有 javax 引用
Get-ChildItem -Recurse -Filter "*.java" | Select-String "import javax\." | Select-Object Path, LineNumber, Line
💡 本项目实际情况:全项目仅 1 处
javax.annotation.PostConstruct(AiGatewayConfig.java),影响极小。项目中未使用 JPA,无javax.persistence引用。
5. MyBatis-Plus 专项注意事项
这是本次升级坑最多的依赖,详细记录如下。
5.1 版本选择
❌ 不要用 3.5.7:与 Spring 6.1 的 MapperFactoryBean 存在兼容问题(即使加了 mybatis-spring 3.0.4 仍报错)。
✅ 使用 3.5.9:修复了与 Spring Boot 3.2 / Spring 6.1 的兼容性问题。
5.2 必须同时引入 mybatis-plus-jsqlparser
3.5.9 起,PaginationInnerInterceptor 从主包拆分到独立模块,不单独引入会编译报错:
找不到符号:PaginationInnerInterceptor
位置:包 com.baomidou.mybatisplus.extension.plugins.inner
<!-- 两个必须同时声明 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
<version>3.5.9</version>
</dependency>
5.3 强制覆盖 mybatis-spring 版本
MyBatis-Plus 3.5.9 传递依赖的 mybatis-spring:2.1.2 与 Spring 6.1 不兼容,必须在根 pom 的 dependencyManagement 中强制锁定 3.0.4(见第 2.2 节)。
报错症状:
Invalid bean definition with name 'xxxMapper':
Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
根本原因:mybatis-spring 2.x 的 MapperFactoryBean.factoryBeanObjectType 返回 String 类型,Spring 6.1 要求必须是 Class 类型。mybatis-spring 3.0.x 修复了此问题。
6. 数据库相关依赖替换
Spring Boot 3.x 对数据库相关依赖有以下必须替换的变更:
6.1 MySQL Connector 更名
<!-- ❌ 旧(Spring Boot 2.x) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!-- ✅ 新(Spring Boot 3.x) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
<scope>runtime</scope>
</dependency>
6.2 Druid Spring Boot Starter 替换
<!-- ❌ 旧(不兼容 Spring Boot 3.x) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<!-- ✅ 新(Spring Boot 3.x 专用) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.21</version>
</dependency>
6.3 Dynamic Datasource 替换
<!-- ❌ 旧(不兼容 Spring Boot 3.x) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- ✅ 新(Spring Boot 3.x 专用) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>4.3.0</version>
</dependency>
7. Maven 配置
7.1 升级 Maven 至 3.9.x
Spring Boot 3.x 管理的 maven-install-plugin:3.1.3、maven-deploy-plugin:3.1.3 等要求 Maven ≥ 3.6.3。
推荐下载:Apache Maven 3.9.15,解压到 E:\code\Java\apache-maven-3.9.15。
7.2 settings.xml 迁移到新版 Maven
⚠️ Maven 3.9.x 默认添加 maven-default-http-blocker**,会拦截所有 HTTP(非 HTTPS)仓库请求。由于内网私服使用 HTTP,必须删除该 mirror 配置 **:
<!-- ❌ Maven 3.9.x 默认配置,必须删除,否则内网 HTTP 仓库全部被拦截 -->
<mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>
7.3 临时设置 JAVA_HOME 执行构建(不修改系统环境变量)
PowerShell:
$env:JAVA_HOME = "E:\software\Java\jdk-21.0.11"
$env:PATH = "E:\code\Java\apache-maven-3.9.15\bin;E:\software\Java\jdk-21.0.11\bin;" + $env:PATH
mvn clean install -DskipTests
CMD:
set "JAVA_HOME=E:\software\Java\jdk-21.0.11"
set "PATH=E:\code\Java\apache-maven-3.9.15\bin;E:\software\Java\jdk-21.0.11\bin;%PATH%"
mvn clean install -DskipTests
8. Dockerfile 更新
8.1 基础镜像
内部镜像 harbor-qz.mail.netease.com/asrd/java-app:1.0.12 需向运维确认是否有 JDK21 版本。
8.2 移除废弃的 JVM GC 参数
JDK9+ 已移除 CMS 垃圾收集器,以下参数在 JDK21 下会导致 JVM 启动失败或警告:
# ❌ 删除以下参数(JDK21 不支持 CMS GC)
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:ParallelCMSThreads=8
-XX:MaxTenuringThreshold=10
# ✅ JDK21 默认使用 G1 GC,无需额外配置
# 可按需保留日志参数:-Xloggc:/path/to/gc.log
9. 常见报错与解决方案
❌ 报错 1:Maven 版本不兼容
The plugin org.apache.maven.plugins:maven-install-plugin:3.1.3 requires Maven version 3.6.3
原因:Maven 版本低于 3.6.3(如 3.3.9)。
解决:升级 Maven 到 3.9.x。
❌ 报错 2:编译器不认识 --release
Fatal error compiling: 无效的标记: --release
原因:maven-compiler-plugin 配置中保留了旧式 <compilerArguments><extdirs>lib</extdirs></compilerArguments>,与 <release> 参数冲突;或者 Maven 调用的实际 JVM 仍是 JDK8(javac 不支持 --release)。
解决:
- 删除
<compilerArguments>配置块 - 确认
JAVA_HOME指向 JDK21,执行mvn -version验证Java version: 21
❌ 报错 3:MapperFactoryBean 类型不兼容
Invalid bean definition with name 'xxxMapper':
Invalid value type for attribute 'factoryBeanObjectType': java.lang.String
原因:mybatis-spring 版本为 2.x,与 Spring 6.1 不兼容。
解决:在根 pom 的 dependencyManagement 中强制锁定 mybatis-spring:3.0.4。
❌ 报错 4:找不到 PaginationInnerInterceptor
找不到符号:PaginationInnerInterceptor
位置:包 com.baomidou.mybatisplus.extension.plugins.inner
原因:MyBatis-Plus 3.5.9 将分页拦截器移至独立模块。
解决:额外引入 mybatis-plus-jsqlparser:3.5.9 依赖。
❌ 报错 5:javax 包找不到
package javax.servlet does not exist
package javax.annotation does not exist
原因:Spring Boot 3.x 迁移到 Jakarta EE 10,javax.* 改为 jakarta.*。
解决:全局搜索替换(见第 4 节)。
❌ 报错 6:内网 HTTP 仓库被拦截
Could not transfer artifact ... from/to maven-default-http-blocker (http://0.0.0.0/)
原因:Maven 3.9.x 默认阻断所有 HTTP 仓库访问。
解决:删除 settings.xml 中的 maven-default-http-blocker mirror 配置。
10. 升级验证清单
按顺序执行,每步通过后再继续:
[ ] 1. mvn -version 确认:Maven ≥ 3.9.x,Java version: 21.0.x
[ ] 2. mvn clean compile — 全量编译通过,无 javax.* 包缺失错误
[ ] 3. mvn clean install -DskipTests — BUILD SUCCESS,全部模块 SUCCESS
[ ] 4. mvn dependency:tree | grep mybatis-spring — 确认版本为 3.0.4
[ ] 5. mvn dependency:tree | grep mybatis-plus — 确认版本为 3.5.9
[ ] 6. 启动应用 — Spring Boot 上下文加载成功,无 BeanDefinition 报错
[ ] 7. 执行一次核心接口请求 — 业务逻辑正常,日志无异常
[ ] 8. mvn test — 单元测试全部通过(或已知失败项有说明)
附:本项目实际升级的 pom.xml 关键变更速查
<!-- 根 pom.xml 核心变更 -->
<!-- 1. Spring Boot 父版本 -->
<version>3.2.12</version> <!-- 原 2.7.13 -->
<!-- 2. Java 编译版本 -->
<maven.compiler.source>21</maven.compiler.source> <!-- 原 8 -->
<maven.compiler.target>21</maven.compiler.target> <!-- 原 8 -->
<java.version>21</java.version> <!-- 原 1.8 -->
<!-- 3. 依赖版本升级 -->
<fastjson.version>2.0.53</fastjson.version> <!-- 原 2.0.43 -->
<lombok version="1.18.34"/> <!-- 原 1.18.22 -->
<commons-lang3 version="3.14.0"/> <!-- 原 3.12.0 -->
<!-- 4. 强制覆盖(在 dependencyManagement 中) -->
<mybatis-spring version="3.0.4"/> <!-- 新增,覆盖 MP 传递的 2.1.2 -->
<!-- 子模块变更(scan/vector) -->
<!-- mybatis-plus-boot-starter: 3.4.1 → 3.5.9 -->
<!-- mybatis-plus-jsqlparser:3.5.9 (新增) -->
<!-- mysql-connector-java:8.0.22 → mysql-connector-j:8.3.0 (groupId 也变了) -->
<!-- druid-spring-boot-starter:1.2.4 → druid-spring-boot-3-starter:1.2.21 -->
<!-- dynamic-datasource-spring-boot-starter:3.4.1 → dynamic-datasource-spring-boot3-starter:4.3.0 -->