Spring Boot 3.x迁移指南:从2.x升级的完整流程和坑点总结

Spring Boot 3.x迁移指南:从2.x升级的完整流程和坑点总结

今年初公司要把所有SpringBoot应用升级到3.x(主要是要用虚拟线程和Native Image),我负责迁移工作。整个过程踩了不少坑,这篇文章分享完整的迁移流程和解决方案。

为什么要升级到Spring Boot 3.x?

先说结论:Spring Boot 3.x不是简单的版本升级,而是一次架构升级

核心变化

  1. Java 17+:Spring Boot 3.x要求Java 17+(Spring Boot 2.x支持Java 8+)
  2. Jakarta EE 9+:包名从javax.*改为jakarta.*(这个改动最大)
  3. Spring Framework 6.x:底层框架升级
  4. GraalVM Native Image支持:可以把应用编译成原生可执行文件
  5. 虚拟线程支持:Spring Boot 3.2+支持Java 21虚拟线程

如果不升级会怎样?

  • Spring Boot 2.x到2025年底就EOL(End of Life)了
  • 新特性(虚拟线程、Native Image)用不了
  • 安全漏洞没人修

迁移前的准备工作

1. 评估影响范围

检查清单

  • 项目用的Java版本(如果是Java 8,要先升级到Java 17)
  • 项目依赖的第三方库(是否支持Spring Boot 3.x)
  • 项目用的javax.*包(要改为jakarta.*
  • 项目用的Spring Cloud版本(要升级到2022.0.0+)

工具推荐

2. 搭建迁移环境

建议

  • 创建新的Git分支(比如migrate-to-springboot-3.x
  • 在测试环境先做迁移,不要直接改生产代码
  • 准备好回滚方案

迁移步骤(详细版)

步骤1:升级Java版本

如果项目用的是Java 8或Java 11,要先升级到Java 17+。

方式1:用SDKMAN管理多版本Java

# 安装SDKMAN
curl -s "https://get.sdkman.io" | bash

# 安装Java 17
sdk install java 17.0.1-tem

# 切换到Java 17
sdk use java 17.0.1-tem

方式2:直接下载JDK

  • 访问Adoptium,下载JDK 17
  • 设置JAVA_HOME环境变量

验证

java -version
# 输出应该包含 "17.0.x"

步骤2:修改pom.xml

修改Spring Boot版本

<!-- 修改前 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.18</version>
</parent>

<!-- 修改后 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
</parent>

修改Spring Cloud版本(如果用了Spring Cloud):

<!-- 修改前 -->
<properties>
    <spring-cloud.version>2021.0.8</spring-cloud.version>
</properties>

<!-- 修改后 -->
<properties>
    <spring-cloud.version>2023.0.0</spring-cloud.version>
</properties>

步骤3:替换javax.*jakarta.*

这是最麻烦的一步。

需要修改的包

修改前修改后
javax.servlet.*jakarta.servlet.*
javax.persistence.*jakarta.persistence.*
javax.validation.*jakarta.validation.*
javax.annotation.*jakarta.annotation.*

示例

// 修改前
import javax.servlet.http.HttpServletRequest;

@RestController
public class TestController {
    @GetMapping("/test")
    public String test(HttpServletRequest request) {
        return "Hello";
    }
}

// 修改后
import jakarta.servlet.http.HttpServletRequest;

@RestController
public class TestController {
    @GetMapping("/test")
    public String test(HttpServletRequest request) {
        return "Hello";
    }
}

自动化工具
用OpenRewrite可以自动完成这个替换:

# 1. 添加OpenRewrite插件到pom.xml
<plugin>
    <groupId>org.openrewrite.maven</groupId>
    <artifactId>rewrite-maven-plugin</artifactId>
    <version>5.31.0</version>
    <configuration>
        <activeRecipes>
            <recipe>org.openrewrite.java.migrate.JavaxToJakarta</recipe>
        </activeRecipes>
    </configuration>
</plugin>

# 2. 运行重构
mvn rewrite:run

步骤4:升级第三方依赖

常见问题:有些第三方库不支持Spring Boot 3.x,需要升级版本。

示例:MyBatis

<!-- 修改前 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.3.1</version>
</dependency>

<!-- 修改后 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

常见依赖的兼容版本

依赖Spring Boot 2.x版本Spring Boot 3.x版本
MyBatis2.3.x3.0.x
Druid1.2.x1.2.20+
Swaggerspringfox 3.0.0springdoc-openapi 2.3.0
Redislettuce 6.xlettuce 6.2+

步骤5:修改配置文件

Spring Boot 3.x对一些配置项做了重命名。

示例

# 修改前(Spring Boot 2.x)
spring:
  mvc:
    throw-exception-if-no-handler-found: true
  resources:
    add-mappings: false

# 修改后(Spring Boot 3.x)
spring:
  mvc:
    throw-exception-if-no-handler-found: true
  web:
    resources:
      add-mappings: false

完整的配置变更列表:参考Spring Boot 3.0 Migration Guide

步骤6:编译和测试

# 1. 编译
mvn clean compile

# 2. 运行测试
mvn test

# 3. 启动应用
mvn spring-boot:run

如果编译报错,根据错误信息逐个修复(大部分是javax.*没改干净)。

如果启动报错,查看日志,常见问题:

  • 配置项改名了 → 参考Migration Guide
  • 依赖版本不兼容 → 升级依赖
  • 反射权限问题(如果用了Native Image)→ 添加@RegisterForReflection注解

常见坑点和解决方案

坑1:Swagger不兼容

问题:Spring Boot 3.x不支持Springfox(Swagger 2),要改用Springdoc OpenAPI。

解决方案

<!-- 移除Springfox -->
<!--
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
-->

<!-- 添加Springdoc OpenAPI -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.3.0</version>
</dependency>

代码改动

// 修改前(Springfox注解)
@Api(tags = "用户管理")
@RestController
public class UserController {
    @ApiOperation("获取用户")
    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getById(id);
    }
}

// 修改后(Springdoc注解)
@Tag(name = "用户管理")
@RestController
public class UserController {
    @Operation(summary = "获取用户")
    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getById(id);
    }
}

坑2:Druid数据源不兼容

问题:Druid 1.2.8以下版本不支持Spring Boot 3.x。

解决方案:升级到Druid 1.2.20+。

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-3-starter</artifactId>
    <version>1.2.20</version>
</dependency>

坑3:Reflection权限问题(Native Image)

问题:如果用了Native Image,反射调用会报错。

解决方案:在reflect-config.json中注册需要反射的类(参考我之前写的GraalVM文章)。

坑4:JUnit测试不兼容

问题:Spring Boot 3.x用JUnit 5,如果项目用的是JUnit 4,要改。

解决方案

// 修改前(JUnit 4)
import org.junit.Test;

public class UserServiceTest {
    @Test
    public void testGetUser() {
        // ...
    }
}

// 修改后(JUnit 5)
import org.junit.jupiter.api.Test;

public class UserServiceTest {
    @Test
    void testGetUser() {
        // ...
    }
}

自动化工具:用OpenRewrite可以自动完成这个替换。

迁移后的验证清单

  • 应用能正常启动
  • 所有单元测试通过
  • 所有API接口正常(用Postman或JMeter测试)
  • 数据库操作正常
  • 缓存(Redis)操作正常
  • 消息队列(MQ)操作正常
  • 日志输出正常
  • 健康检查接口正常(/actuator/health
  • 性能指标正常(用JMeter压测)

总结

Spring Boot 3.x迁移工作量不小,但这是必须做的。我的建议:

  1. 新项目:直接用Spring Boot 3.2 + Java 21(一步到位)
  2. 老项目:制定迁移计划,逐步迁移(先迁移不重要的服务)
  3. 测试优先:迁移完后一定要做充分的测试(单元测试 + 集成测试 + 压测)
  4. 工具辅助:用Spring Boot Migrator和OpenRewrite自动化迁移,减少手动改代码的工作量

最后说一句:迁移虽然麻烦,但迁移后能用上虚拟线程、Native Image这些新特性,还是很值得的


参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值