news 2026/4/8 13:04:36

从 Spring Boot 2.x 到 3.5.x + JDK21:一次完整的生产环境迁移实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从 Spring Boot 2.x 到 3.5.x + JDK21:一次完整的生产环境迁移实战

升级背景

在私有化部署过程中,客户使用安全扫描工具检测到大量安全漏洞,主要集中在:

  • 框架版本过低:Spring Boot 2.1.6.RELEASE(发布于 2019 年)
  • JDK 版本过旧:JDK 8(缺乏最新安全补丁)
  • 第三方依赖:多个依赖存在已知 CVE 漏洞

基于安全合规和长期维护的考虑,决定进行大版本升级。

  • 当前版本:Spring Boot 2.1.6.RELEASE + JDK 8
  • 目标版本Spring Boot 3.5.4 + JDK 21 LTS

升级目标与核心变化

主要变化

类别变化内容迁移方式
命名空间javax.* → jakarta.*自动化迁移
JDK 版本Java 8 → Java 21 LTS自动化迁移 + 手动调整
第三方依赖大量依赖需要升级手动处理
API 文档Swagger 2.x → SpringDoc OpenAPI 3.x配置调整
安全配置WebSecurityConfigurerAdapter 废弃重写配置类

为什么选择自动化迁移?
前两项(命名空间和 JDK 版本)涉及的代码改动量极大,手动修改容易出错且效率低下。

OpenRewrite作为业界成熟的自动化重构工具,可以完成大部分繁琐工作。

完整升级步骤

第一阶段:准备工作(JDK 8 环境)

代码分支管理

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-shell"><span style="color:#015692"># </span>确保主分支代码为最新 git checkout dev git pull origin dev <span style="color:#015692"> # </span>创建升级专用分支 git checkout -b upgrade/springboot3-jdk21 </code></span></span>

引入 OpenRewrite Maven 插件

什么是 OpenRewrite?

OpenRewrite 是一个自动化代码重构和迁移工具,专为 Java 生态系统设计。

核心优势

  1. 精确安全:在 AST(抽象语法树)层面操作,不会破坏代码结构
  2. 批量处理:一次性处理整个代码库
  3. 可预览:使用rewrite:dryRun查看变更预览
  4. 可定制:支持声明式(YAML)或编程式自定义规则

工作原理

OpenRewrite 通过解析源代码生成无损语法树(LST),在 AST 层面进行精确转换,完整保留:

  • 原始格式和缩进
  • 所有注释
  • 代码风格

配置方式

pom.xml<plugins>节点下添加:

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-xml"><<span style="color:#b75501">plugin</span>> <<span style="color:#b75501">groupId</span>>org.openrewrite.maven</<span style="color:#b75501">groupId</span>> <<span style="color:#b75501">artifactId</span>>rewrite-maven-plugin</<span style="color:#b75501">artifactId</span>> <<span style="color:#b75501">version</span>>6.15.0</<span style="color:#b75501">version</span>> <<span style="color:#b75501">configuration</span>> <<span style="color:#b75501">exportDatatables</span>>true</<span style="color:#b75501">exportDatatables</span>> <<span style="color:#b75501">activeRecipes</span>> <span style="color:#656e77"><!-- 升级到 Java 21 --></span> <<span style="color:#b75501">recipe</span>>org.openrewrite.java.migrate.UpgradeToJava21</<span style="color:#b75501">recipe</span>> <span style="color:#656e77"><!-- JUnit 4 to 5 --></span> <<span style="color:#b75501">recipe</span>>org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration</<span style="color:#b75501">recipe</span>> <span style="color:#656e77"><!-- Spring Boot 3.4(插件暂不支持 3.5,升级后手动改) --></span> <<span style="color:#b75501">recipe</span>>org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_4</<span style="color:#b75501">recipe</span>> </<span style="color:#b75501">activeRecipes</span>> </<span style="color:#b75501">configuration</span>> <<span style="color:#b75501">dependencies</span>> <<span style="color:#b75501">dependency</span>> <<span style="color:#b75501">groupId</span>>org.openrewrite.recipe</<span style="color:#b75501">groupId</span>> <<span style="color:#b75501">artifactId</span>>rewrite-migrate-java</<span style="color:#b75501">artifactId</span>> <<span style="color:#b75501">version</span>>3.14.1</<span style="color:#b75501">version</span>> <<span style="color:#b75501">scope</span>>runtime</<span style="color:#b75501">scope</span>> </<span style="color:#b75501">dependency</span>> <<span style="color:#b75501">dependency</span>> <<span style="color:#b75501">groupId</span>>org.openrewrite.recipe</<span style="color:#b75501">groupId</span>> <<span style="color:#b75501">artifactId</span>>rewrite-spring</<span style="color:#b75501">artifactId</span>> <<span style="color:#b75501">version</span>>6.11.1</<span style="color:#b75501">version</span>> </<span style="color:#b75501">dependency</span>> </<span style="color:#b75501">dependencies</span>> </<span style="color:#b75501">plugin</span>> </code></span></span>

配方(Recipe)说明

  • UpgradeSpringBoot_3_4 :升级至 Spring Boot 3.4.x(插件暂不支持 3.5,升级后手动修改版本号即可)
  • UpgradeToJava21 :升级至 JDK 21(Spring Boot 配方仅升级到 JDK 17,需额外添加此配方)
  • SpringBoot2JUnit4to5Migration :升级测试框架,避免自动化测试报错

提示:你也可以编写自定义配方来处理项目特定的迁移需求。

执行自动化迁移

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-shell">mvn rewrite:run </code></span></span>

或者在 IDEA 中通过 Maven 面板执行:

执行时间:几分钟到几十分钟不等,取决于项目规模。

可能遇到的问题:

  1. 如果某些类包含特殊代码导致报错,可以先注释掉,待升级完成后再处理
  2. 执行完成后可以删除该插件(也可以保留,以便后续增量升级)

OpenRewrite 自动完成的变更

执行完成后,主要变化包括:

依赖升级

  • pom.xml中的依赖版本自动升级
  • Spring Boot 版本升级到 3.4.x(手动改为 3.5.4)

包名变更

  • javax.servlet.* → jakarta.servlet.*
  • javax.persistence.* → jakarta.persistence.*
  • javax.validation.* → jakarta.validation.*

API 文档迁移

  • Swagger 2.x → SpringDoc OpenAPI 3.x

JDK 新特性应用

  • Text Blocks:多行字符串的优雅处理
<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#656e77">// 自动转换为</span> <span style="color:#b75501">String</span> <span style="color:#54790d">json</span> <span style="color:#ab5656">=</span> <span style="color:#54790d">""" { "name": "user", "age": 18 } """</span>; </code></span></span>
  • instanceof 模式匹配:简化类型判断和转换
<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">if</span> (obj <span style="color:#015692">instanceof</span> String s) { System.out.println(s.toUpperCase()); } </code></span></span>
  • String.formatted():替代String.format()
<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#54790d">"Hello, %s!"</span>.formatted(name); </code></span></span>
  • 集合增强: getFirst() 替代 get(0)
  • @Serial注解:标记序列化相关字段

第三方库升级

  • Apache HttpClient
  • Apache Commons 系列
  • 其他常用工具库

增量合并场景处理

场景:执行 Rewrite 后,旧分支又有代码提交,合并时出现大量javax包名和 Swagger 注解冲突。

解决方案:使用 IntelliJ IDEA 自带的 Refactor 功能(本质也是基于 OpenRewrite)

操作步骤:

  1. 打开 IDEA,选择Refactor → Migrate Packages and Classes
  2. 选择迁移规则(javax → jakarta)
  3. 预览变更并执行

第二阶段:环境切换(JDK 21 环境)

重要分界线:以下操作需在 JDK 21 环境下进行。


6. 修改 IDEA 项目配置

修改 SDK 和 Language Level(快捷键:Ctrl + Alt + Shift + S):

修改 Modules 的 Language Level:

修改 Java Compiler(快捷键:Ctrl + Alt + S):




核心问题与解决方案

问题一:Hibernate DDL Auto 的陷阱

严重警告:在完成以下配置前,切勿启动项目!否则可能导致数据库结构被错误修改。


问题背景

新旧版本 Hibernate 的行为差异:

为什么要禁用?

在生产环境中使用spring.jpa.hibernate.ddl-auto=update存在严重风险:

  1. 数据安全风险:自动更新可能导致意外的数据丢失或结构变更
  2. 性能问题:启动时全表检查会显著增加应用启动时间
  3. 版本控制缺失:无法追踪数据库变更历史,不利于团队协作和回滚
  4. 升级后风险更高:Hibernate 6.x 的校验更严格,误操作概率增加

解决方案

方案一:配置优先级控制(推荐)

在 CI/CD 启动脚本中设置 VM 参数:

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-shell">java -jar app.jar -Dspring.jpa.hibernate.ddl-auto=none </code></span></span>

优先级:VM 参数 > 配置中心(Apollo/Nacos) > application.properties

方案二:使用专业的数据库版本管理工具

推荐使用FlywayLiquibase管理数据库脚本:

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-xml"><<span style="color:#b75501">dependency</span>> <<span style="color:#b75501">groupId</span>>org.flywaydb</<span style="color:#b75501">groupId</span>> <<span style="color:#b75501">artifactId</span>>flyway-core</<span style="color:#b75501">artifactId</span>> </<span style="color:#b75501">dependency</span>> </code></span></span>

方案三:结构对比工具

  • Navicat:提供结构同步功能
  • DataGrip:IntelliJ 系产品,支持数据库结构对比

问题二:Spring Security 配置迁移

核心变化

  • WebSecurityConfigurerAdapter已废弃
  • 推荐使用Lambda DSL配置方式
  • 配置方式从继承改为 Bean 注册

迁移示例

旧版配置(Spring Security 5.x):

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">@Configuration</span> <span style="color:#015692">@EnableWebSecurity</span> <span style="color:#015692">public</span> <span style="color:#015692">class</span> <span style="color:#b75501">SecurityConfig</span> <span style="color:#015692">extends</span> <span style="color:#b75501">WebSecurityConfigurerAdapter</span> { <span style="color:#015692">@Override</span> <span style="color:#015692">protected</span> <span style="color:#015692">void</span> <span style="color:#b75501">configure</span>(HttpSecurity http) <span style="color:#015692">throws</span> Exception { http .csrf().disable() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers(<span style="color:#54790d">"/api/public/**"</span>).permitAll() .anyRequest().authenticated(); } } </code></span></span>

新版配置(Spring Security 6.x):

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">@Configuration</span> <span style="color:#015692">@EnableWebSecurity</span> <span style="color:#015692">public</span> <span style="color:#015692">class</span> <span style="color:#b75501">SecurityConfig</span> { <span style="color:#015692">private</span> <span style="color:#015692">final</span> TokenProvider tokenProvider; <span style="color:#015692">public</span> <span style="color:#b75501">SecurityConfig</span>(TokenProvider tokenProvider) { <span style="color:#b75501">this</span>.tokenProvider = tokenProvider; } <span style="color:#015692">@Bean</span> <span style="color:#015692">public</span> SecurityFilterChain <span style="color:#b75501">filterChain</span>(HttpSecurity http) <span style="color:#015692">throws</span> Exception { http .csrf(AbstractHttpConfigurer::disable) .sessionManagement(sessionManagement -> sessionManagement .sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(authorizeRequests -> authorizeRequests <span style="color:#656e77">// 允许所有 OPTIONS 请求</span> .requestMatchers(OPTIONS, <span style="color:#54790d">"**"</span>).permitAll() .requestMatchers( <span style="color:#54790d">"/swagger-ui/**"</span>, <span style="color:#54790d">"/v3/api-docs/**"</span>, <span style="color:#54790d">"/swagger-resources/**"</span>, <span style="color:#54790d">"/images/**"</span>, <span style="color:#54790d">"/webjars/**"</span>).permitAll() .anyRequest().authenticated()) .addFilterBefore(<span style="color:#015692">new</span> <span style="color:#b75501">JWTFilter</span>(tokenProvider), UsernamePasswordAuthenticationFilter.class); <span style="color:#015692">return</span> http.build(); } } </code></span></span>

RequestMatcher 调整注意事项

  1. 新增 SpringDoc 路径(必须)
<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java">/swagger-ui<span style="color:#656e77">/** /v3/api-docs/** </span></code></span></span>

修正通配符写法

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java">❌ 错误: <span style="color:#656e77">//**/*.js</span> ✅ 正确: <span style="color:#656e77">/**/*.js 否则会抛出 PatternParseException </span></code></span></span>

问题三:SpringDoc OpenAPI 配置

Swagger → SpringDoc 迁移

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"> <!-- 移除旧的 Swagger 依赖 --> <!-- <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> </dependency> --> <!-- 添加新的 SpringDoc 依赖 --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version><span style="color:#b75501">2.3</span><span style="color:#b75501">.0</span></version> </dependency> </code></span></span>

配置示例

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">@Configuration</span> <span style="color:#015692">@OpenAPIDefinition</span> <span style="color:#015692">public</span> <span style="color:#015692">class</span> <span style="color:#b75501">SwaggerConfig</span> { <span style="color:#015692">@Bean</span> <span style="color:#015692">public</span> OpenAPI <span style="color:#b75501">openAPI</span>() { <span style="color:#b75501">OpenAPI</span> <span style="color:#54790d">openAPI</span> <span style="color:#ab5656">=</span> <span style="color:#015692">new</span> <span style="color:#b75501">OpenAPI</span>(); openAPI.info(<span style="color:#015692">new</span> <span style="color:#b75501">Info</span>().title(<span style="color:#54790d">"API 文档"</span>).version(<span style="color:#54790d">"1.0"</span>)); <span style="color:#656e77">// 配置 Authorization 登录鉴权</span> Map<String, SecurityScheme> map = Map.of(<span style="color:#54790d">"Authorization"</span>, <span style="color:#015692">new</span> <span style="color:#b75501">SecurityScheme</span>() .type(SecurityScheme.Type.APIKEY) .in(SecurityScheme.In.HEADER) .name(<span style="color:#54790d">"Authorization"</span>)); openAPI.components(<span style="color:#015692">new</span> <span style="color:#b75501">Components</span>().securitySchemes(map)); map.keySet().forEach(key -> openAPI.addSecurityItem(<span style="color:#015692">new</span> <span style="color:#b75501">SecurityRequirement</span>().addList(key))); <span style="color:#015692">return</span> openAPI; } } </code></span></span>

注解对应关系

Swagger 2.xSpringDoc OpenAPI 3.x
@Api@Tag
@ApiOperation@Operation
@ApiParam@Parameter
@ApiModel@Schema
@ApiModelProperty@Schema

访问地址变更

原 Swagger UI 地址:http://localhost:8080/swagger-ui.html
新 SpringDoc 地址:http://localhost:8080/swagger-ui/index.html

问题四:依赖冲突与安全漏洞修复

检测工具

使用 IDEA 自带的依赖分析工具:

必须升级的依赖(存在高危漏洞)

推荐使用OWASP Dependency-CheckSnyk扫描:

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-shell">mvn dependency-check:check </code></span></span>

解决依赖冲突的技巧

问题:Maven 依赖解析采用"最短路径优先"和"第一声明优先"原则,可能导致旧版本覆盖新版本。

解决方案:显式声明期望的版本

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><dependencies> <!-- 显式声明 Spring Framework 版本,避免被传递依赖覆盖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version><span style="color:#b75501">6.1</span><span style="color:#b75501">.3</span></version> </dependency> </dependencies> </code></span></span>

快速检测技巧

在 IDEA 的 Maven 依赖树中搜索RELEASE,Spring 新版本已不使用RELEASE后缀,搜索到的基本都是旧版本。

问题五:URL 尾斜杠匹配策略变更

行为变化

版本行为
Spring Boot 2.x/api/user/get 和 /api/user/get/ 视为同一接口
Spring Boot 3.x/api/user/get 和 /api/user/get/ 视为不同接口

常见导致尾斜杠的情况

  • Case 1:类注解带尾斜杠
<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">@RequestMapping("/api/user/")</span> <span style="color:#015692">public</span> <span style="color:#015692">class</span> <span style="color:#b75501">UserController</span> { <span style="color:#015692">@PostMapping("login")</span> <span style="color:#656e77">// 实际路径:/api/user/login</span> } </code></span></span>

Case 2:空字符串映射

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">@RequestMapping("/api/user")</span> <span style="color:#015692">public</span> <span style="color:#015692">class</span> <span style="color:#b75501">UserController</span> { <span style="color:#015692">@PostMapping("")</span> <span style="color:#656e77">// 实际路径:/api/user/(带尾斜杠!)</span> } </code></span></span>

Case 3:根路径映射

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">@PostMapping("/")</span> <span style="color:#656e77">// 实际路径:/(带尾斜杠)</span> </code></span></span>


**** 检查方式

  1. IDEA Endpoints 工具窗口:查看所有端点
  2. SpringDoc UI:访问 Swagger 页面检查

临时解决方案(不推荐长期使用)

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><span style="color:#015692">import</span> org.springframework.context.annotation.Configuration; <span style="color:#015692">import</span> org.springframework.web.servlet.config.annotation.PathMatchConfigurer; <span style="color:#015692">import</span> org.springframework.web.servlet.config.annotation.WebMvcConfigurer; <span style="color:#015692">@Configuration</span> <span style="color:#015692">public</span> <span style="color:#015692">class</span> <span style="color:#b75501">WebConfiguration</span> <span style="color:#015692">implements</span> <span style="color:#b75501">WebMvcConfigurer</span> { <span style="color:#015692">@Override</span> <span style="color:#015692">public</span> <span style="color:#015692">void</span> <span style="color:#b75501">configurePathMatch</span>(PathMatchConfigurer configurer) { <span style="color:#656e77">// 设 置 为 true 以 忽 略 尾 斜 杠 , 恢 复 旧 版 本 行 为</span> configurer.setUseTrailingSlashMatch(<span style="color:#b75501">true</span>); } } </code></span></span>

注意__: ·setUseTrailingSlashMatch在 Spring 6.x 后已标记为废弃,后续版本将删除。建议逐步修正所有端点,去除尾斜杠。

根本解决方案

  1. 修正所有 Controller 的路径映射
  2. 通知前端团队同步修改调用路径
  3. 如果有硬编码的 URL,全局搜索并修正
  4. 使用测试确保前后端调用正常

问题六:Apache POI / EasyExcel 升级

背景

Apache POI 旧版本(< 5.0)存在多个 CVE 安全漏洞,必须升级。

推荐方案

对于新项目:直接使用FastExcel

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><dependency> <groupId>cn.idev.excel</groupId> <artifactId>fastexcel</artifactId> <version><span style="color:#b75501">1.0</span><span style="color:#b75501">.0</span></version> </dependency> </code></span></span>

对于使用 EasyExcel 的旧项目

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java"><dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version><span style="color:#b75501">4.0</span><span style="color:#b75501">.3</span></version> </dependency> </code></span></span>

说明:EasyExcel 已不再维护,FastExcel 是社区维护的替代方案,API 基本兼容。

迁移注意事项

EasyExcel 跨大版本升级(2.x → 4.x)API 变化较大,主要改动:

1.监听器接口方法签名调整

2.部分工具类包路径变更

3.自定义转换器需要适配新接口

建议参考官方迁移文档:EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网

问题七:JDK 模块化限制(--add-opens)

问题现象

某些依赖库使用反射访问 JDK 内部 API,在 JDK 9+ 模块化系统下会报错:

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java">InaccessibleObjectException: Unable to make field accessible: <span style="color:#015692">module</span> java.base does not <span style="color:#54790d">"opens java.net"</span> to unnamed <span style="color:#015692">module</span> </code></span></span>

解决方案

在 IDEA 运行配置中添加 VM 参数:

开启 VM 参数配置(默认隐藏):

解决方案

在 IDEA 运行配置中添加 VM 参数:

开启 VM 参数配置(默认隐藏):

常见需要开放的模块

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java">--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED </code></span></span>

问题八:过期配置属性警告

问题现象

启动时出现警告:

<span style="color:#000000"><span style="background-color:#fefef2"><code class="language-java">Property <span style="color:#54790d">'spring.xxx.yyy'</span> is deprecated </code></span></span>

解决方案:

  1. 查看 Spring Boot 官方迁移文档

  2. 使用 IDEA 的智能提示查看替代属性

  3. 修改配置文件( 常见过期属性:application.yml或配置中心)

常见过期属性:

过期属性替代属性
spring.datasource.type自动推断,无需配置
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults已移除
management.metrics.export.prometheus.enabledmanagement.prometheus.metrics.export.enabled

完整测试清单

升级完成后,务必进行全面的回归测试:

  • Spring Security:认证、授权是否正常
  • SpringDoc:API 文档是否可访问( /swagger-ui/index.html )
  • 数据库操作:JPA/MyBatis 是否正常工作
  • 缓存:Redis/Caffeine 等缓存是否生效
  • 消息队列:RabbitMQ/Kafka 等是否正常
  • 定时任务:Scheduled/Quartz 是否按预期执行
  • 文件上传/下载:文件 IO 操作是否正常
  • 业务功能:核心业务流程是否正常(重点关注有代码改动的地方)
  • 性能测试:对比升级前后的性能指标

升级感悟

框架层面的变化趋势

通过这次升级,我观察到现代框架的一些发展趋势:

  1. 校验更严格
  • Spring 不再容忍 URL 尾斜杠的模糊匹配
  • 循环依赖检测更严格(默认禁止)
  • Hibernate 对实体状态的校验更精确
  1. 安全性优先
  • 默认配置更保守
  • 废弃不安全的 API
  • 强制升级修复已知漏洞
  1. 现代化 API
  • Lambda DSL 配置风格
  • 函数式编程支持
  • 更简洁的 API 设计

依赖选择建议

基于这次升级经验,对于第三方库的选择建议:

优先选择

✅ 国际主流项目(Apache、Spring 生态等)

✅ 有完善文档和测试的项目

✅ 活跃维护且社区规模大的项目

✅ 语义化版本管理清晰的项目

谨慎选择

⚠️ 缺乏自动化测试的项目

⚠️ 长期未更新的项目

⚠️ API 设计不稳定、频繁 Breaking Change 的项目

⚠️ 文档不全、维护团队不稳定的项目

自动化迁移的价值

OpenRewrite 等自动化工具在大版本升级中的价值无可替代:

  • 减少 90% 以上的机械性改动
  • 避免手工替换导致的遗漏
  • 保持代码风格和注释
  • 降低升级风险

建议在日常开发中也关注此类工具,提升团队整体效率。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/7 4:24:31

互联网大厂Java后端面试中常见面试题及其答案

java中的四种引用有哪些 java中的四种引用有&#xff1a;强引用、软引用、弱引用和虚引用。不同的引用类型&#xff0c;主要体现的是对象不同的可达性&#xff08;reachable&#xff09;状态和对垃圾收集的影响。 强引用&#xff08;"Strong" Reference&#xff09…

作者头像 李华
网站建设 2026/3/22 15:02:51

大模型调用MCP工具竟浪费这么多Token?代码执行模式拯救AI原生应用

直接调用工具时&#xff0c;每次工具定义和执行结果都会占用上下文资源。而让智能体通过编写代码来调用工具&#xff0c;能实现更好的扩展性&#xff0c;以下是借助 MCP 实现这一方案的具体原理。 模型上下文协议&#xff08;Model Context Protocol&#xff0c;简称 MCP&#…

作者头像 李华
网站建设 2026/4/7 15:50:05

【高阶技术揭秘】:从Dify日志看懂重排序算法的隐秘逻辑

第一章&#xff1a;从Dify日志窥探重排序技术的本质在构建现代检索增强生成&#xff08;RAG&#xff09;系统时&#xff0c;重排序&#xff08;Re-ranking&#xff09;作为提升结果相关性的关键步骤&#xff0c;其内部机制往往隐藏于框架的日志细节之中。通过分析 Dify 平台的运…

作者头像 李华
网站建设 2026/4/7 15:50:33

还在为多语言语音识别发愁?Dify 1.7.0一招破解行业痛点

第一章&#xff1a;Dify 1.7.0 音频多语言支持全新升级Dify 1.7.0 版本在语音处理能力上实现了重大突破&#xff0c;尤其在音频的多语言识别与合成功能方面进行了全面增强。此次升级使得系统能够更精准地识别包括中文、英文、西班牙语、法语和日语在内的多种语言&#xff0c;并…

作者头像 李华
网站建设 2026/4/8 12:49:08

【Docker Scout漏洞修复全流程】:手把手教你7步闭环响应安全威胁

第一章&#xff1a;Docker Scout漏洞修复流程概述Docker Scout 是 Docker 官方提供的镜像安全分析工具&#xff0c;能够自动扫描容器镜像中的已知漏洞&#xff0c;并提供详细的修复建议。它集成在 Docker CLI 和 Docker Hub 中&#xff0c;帮助开发者在构建和部署阶段提前识别风…

作者头像 李华