1. 项目背景与升级必要性Spring Boot从2.x到3.x的跨越式升级本质上是一次技术架构的重大演进。作为长期维护Spring Boot 2.7.18项目的技术负责人我最初对升级持保守态度——直到发现官方将在2023年11月停止对2.7.x的维护支持。这意味着继续使用旧版本将面临安全漏洞无人修复的风险这才促使团队下定决心进行技术升级。这次升级的核心挑战在于Spring Boot 3.x最低要求JDK 17而我们的生产环境仍运行在JDK 8上。更棘手的是Jakarta EE 9的命名空间变更从javax.到jakarta.导致大量依赖库需要同步更新。经过两周的攻坚我们最终成功将整套系统迁移到Spring Boot 3.5.8过程中积累的经验值得与各位同行分享。2. 升级前的准备工作2.1 环境兼容性检查清单在开始升级前必须完成以下环境审计JDK版本确认本地和CI环境都已安装JDK 17推荐Azul Zulu 17.0.8IDE支持IntelliJ IDEA需要2021.3版本才能完全兼容Spring Boot 3.x构建工具Gradle 7.5或Maven 3.6.3建议使用Gradle的版本目录功能管理依赖数据库驱动MySQL Connector/J需要8.0PostgreSQL JDBC需要42.3.0重要提示千万不要在生产环境直接尝试升级建议使用Docker创建隔离的测试环境镜像可参考FROM eclipse-temurin:17-jdk-jammy RUN apt-get update apt-get install -y maven2.2 依赖库影响评估使用mvn dependency:tree或gradle dependencies生成依赖树重点关注这些易出问题的库依赖类型2.x版本3.x适配版本变更说明持久层spring-data-jpa 2.7.x3.0.x方法签名变更文档springfox 3.0.0springdoc-openapi 2.1.0完全重写安全spring-security 5.8.x6.1.x配置方式变更模板thymeleaf 3.0.x3.1.x方言注册方式变化3. 分步升级实操指南3.1 基础框架升级步骤修改pom.xml/gradle.build中的父POM!-- 原配置 -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version /parent !-- 新配置 -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.0.8/version !-- 建议先升到3.0.x再逐步到3.5.8 -- /parent处理Jakarta命名空间变更# 使用OpenRewrite进行自动化迁移需Java 17环境运行 mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \ -Drewrite.recipeArtifactCoordinatesorg.openrewrite.recipe:rewrite-spring:LATEST \ -Drewrite.activeRecipesorg.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0特别处理Hibernate 6.x的变更// 旧版配置 Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { // ... properties.put(hibernate.dialect, org.hibernate.dialect.MySQL5Dialect); } // 新版配置 Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { // ... properties.put(hibernate.dialect, org.hibernate.dialect.MySQLDialect); // 移除版本号 }3.2 常见组件适配方案3.2.1 Spring Security 6.x适配最重大的变更来自CSRF保护机制的调整// 旧版配置 http.csrf().disable(); // 新版配置 http.csrf(csrf - csrf.disable()); // Lambda DSL风格3.2.2 文档工具迁移从Springfox迁移到springdoc-openapi的配置示例Configuration public class OpenApiConfig { Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info().title(API文档) .version(3.0) .contact(new Contact().name(团队))); } }4. 疑难问题排查实录4.1 典型编译错误解决方案问题1javax包找不到错误: 程序包javax.servlet不存在解决方案检查是否漏掉了jakarta.servlet:jakarta.servlet-api依赖使用IDE的全局替换功能CtrlShiftR将javax.改为jakarta.问题2Hibernate懒加载异常org.hibernate.LazyInitializationException: could not initialize proxy解决方案# 在application.properties中增加 spring.jpa.properties.hibernate.enable_lazy_load_no_transtrue4.2 运行时异常处理问题3Actuator端点404curl http://localhost:8080/actuator/health # 返回404解决方案management: endpoints: web: exposure: include: * endpoint: health: show-details: always5. 升级后的验证策略5.1 自动化测试保障建议在CI流水线中加入以下检查项# GitHub Actions示例 jobs: verify: steps: - run: mvn test -Dspring.profiles.activetest - run: | curl -sSf http://localhost:8080/actuator/health | \ jq -e .status UP || exit 15.2 性能基准测试使用JMeter进行升级前后对比测试重点关注平均响应时间变化应15%差异GC暂停时间JDK17的ZGC应该表现更好内存占用建议使用VisualVM监控6. 回滚方案设计尽管我们希望一次升级成功但必须准备回滚方案代码回滚Git tag标记发布版本数据库备份mysqldump全量备份环境隔离通过Docker网络隔离新旧版本服务经验之谈在实际操作中我们采用了蓝绿部署策略通过Nginx流量切换确保零停机回滚。配置示例upstream old { server 192.168.1.10:8080; } upstream new { server 192.168.1.20:8080; } server { location / { proxy_pass http://$target; } }7. 升级后的优化建议成功升级到Spring Boot 3.5.8后可以考虑这些增强措施启用GraalVM原生镜像编译需添加spring-boot-starter-native依赖迁移到Spring Security 6.1的新密码存储方案试用Spring Boot 3.x新增的ProblemDetail错误响应标准经过这次升级我们的应用启动时间减少了23%内存占用下降18%。最大的收获是终于可以放心使用Records、Text Blocks等JDK17新特性了。对于仍在犹豫是否升级的团队我的建议是越早开始迁移技术债的利息就越低。