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.PostConstructAiGatewayConfig.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.xMapperFactoryBean.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.3maven-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)。

解决

  1. 删除 <compilerArguments> 配置块
  2. 确认 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 -->