欢迎你来读这篇博客,这篇博客主要是关于 OpenRewrite 的原理、使用方式和实战落地。
它不是一个“格式化工具”,也不是简单的“全局替换工具”,而是一个面向大规模代码库的自动化重构与迁移工具。对于 Java 后端项目来说,OpenRewrite 特别适合处理 Spring Boot 升级、JDK 升级、JUnit 迁移、依赖治理和老 API 清理这类重复但又容易出错的工作。
序言 在真实项目里,依赖升级从来不是只改一个版本号那么简单。
比如你把 Spring Boot 从 2.7 升到 3.5,pom.xml 里版本号确实只需要几行改动,但代码里可能会出现这些问题:
1 2 3 import javax.servlet.http.HttpServletRequest;import javax.validation.Valid;import javax.persistence.Entity;
到了 Spring Boot 3 / Spring Framework 6 / Jakarta EE 之后,这些包名需要迁移到:
1 2 3 import jakarta.servlet.http.HttpServletRequest;import jakarta.validation.Valid;import jakarta.persistence.Entity;
如果项目小,手动搜一搜也能改;如果是几十个微服务、几百个模块,那就不是“加班一晚”的问题了,而是“祖传技术债考古现场”。
这时就轮到 OpenRewrite 上场。
正文 1. OpenRewrite 是什么? OpenRewrite 是一个开源的自动化重构生态,用来对源码、构建文件、配置文件进行可重复、可审查的自动化修改。
它的核心能力是:
1 2 3 4 5 读取项目源码 解析成带语义信息的 Lossless Semantic Tree 执行一个或多个 Recipe 生成代码变更 通过 git diff / PR / MR 进行人工 review
可以简单理解为:
1 OpenRewrite = 自动化代码迁移引擎 + 大量可复用迁移规则 + Maven / Gradle 执行插件
它能做的事情包括:
场景
示例
JDK 升级
Java 8 → Java 17 / 21
Spring 升级
Spring Boot 2.x → Spring Boot 3.x
包名迁移
javax.* → jakarta.*
测试框架迁移
JUnit 4 → JUnit Jupiter
构建文件治理
升级 Maven 插件、调整依赖版本、删除无用依赖
代码规范治理
删除无用 import、替换过时代码写法
安全治理
替换存在风险的 API 或依赖组合
多仓库治理
在企业多个服务中批量执行同一套迁移规则
它最有价值的地方不是“帮你省几分钟”,而是让复杂升级变得:
2. OpenRewrite 和 Renovate / Dependabot 的区别 这几个工具经常被放在一起讨论,但它们分工不同。
工具
核心作用
主要修改对象
Dependabot
GitHub 依赖升级与安全修复
依赖版本、lock 文件
Renovate
更强的依赖升级机器人
依赖版本、Docker 镜像、CI 配置、lock 文件
OpenRewrite
自动化代码重构和迁移
Java 代码、配置文件、构建文件、依赖文件
举个 Spring Boot 升级的例子:
1 2 3 Renovate / Dependabot:发现 Spring Boot 有新版本,提交升级版本号的 PR。 OpenRewrite:把代码里的 javax、旧配置、旧 API 一起迁移掉。 CI:验证编译、测试、打包是否通过。
所以它们不是竞争关系,更像组合拳:
flowchart LR
A[Renovate / Dependabot\n发现依赖升级机会] --> B[提交依赖升级 PR]
B --> C[OpenRewrite\n执行源码和配置迁移]
C --> D[CI 编译与测试]
D --> E[人工 Review]
E --> F[合并上线]
3. OpenRewrite 的核心概念 3.1 Recipe:重构规则 Recipe 是 OpenRewrite 最核心的概念,可以理解为“自动化重构规则”。
比如:
1 org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5
这个 Recipe 用来执行 Spring Boot 3.5 迁移。
再比如:
1 org.openrewrite.java.testing.junit5.JUnit4to5Migration
这个 Recipe 用来把 JUnit 4 测试迁移到 JUnit Jupiter。
Recipe 可以是一个很小的规则,比如删除无用 import,也可以是一个组合规则,内部包含几十个子规则。
3.2 LST:Lossless Semantic Tree OpenRewrite 不是简单正则替换,它会把源码解析成带语义信息的树结构,通常称为 Lossless Semantic Tree。
“Lossless” 的意思是尽量保留源码原本的信息,比如:
1 2 3 4 5 6 注释 空格 换行 import 顺序 代码结构 类型信息
所以它比普通字符串替换更安全。
比如你想替换一个方法调用,正则可能误伤注释、字符串、同名方法;OpenRewrite 能基于类型和语法结构判断:这到底是不是你要改的那个 API。
3.3 Visitor:遍历和修改源码 底层真正修改代码的是 Visitor。
你可以把它理解为:
1 2 Recipe 决定要做什么。 Visitor 负责走进代码树里,把该改的节点改掉。
普通使用者多数时候不用自己写 Visitor,直接使用官方 Recipe 即可。
3.4 DataTables:迁移报告 OpenRewrite 还可以导出 DataTables,用来记录迁移过程中发现了什么、改了什么。
比如:
1 2 3 4 哪些依赖被升级 哪些文件被修改 哪些 API 被替换 哪些地方需要人工处理
在企业落地时,这个能力很有用,因为你可以把一次迁移做成可观测、可统计、可复盘的工程动作,而不是“某个同事本地跑了个脚本”。
4. 环境准备 本文示例以 2026 年 6 月 12 日官方文档可见版本为参考:
模块
示例版本
rewrite-maven-plugin
6.41.0
rewrite-gradle-plugin
7.34.0
rewrite-spring
6.32.1
rewrite-testing-frameworks
3.37.0
建议环境:
1 2 3 4 JDK:17 或 21 Maven:3.6+ Gradle:4.0+ Git:保持工作区干净
正式操作前先确认工作区干净:
如果不是干净状态,先提交或 stash:
1 2 3 4 5 git add . git commit -m "chore: save current work before openrewrite" git stash push -m "before openrewrite"
强烈建议新建分支:
1 git checkout -b chore/openrewrite-migration
5. Maven 项目实战:不修改 pom,直接跑 OpenRewrite 这是最适合初次尝试的方式,因为不用先改项目的 pom.xml。
5.1 dryRun:只看会改什么,不真正修改文件 以 Spring Boot 2.x → Spring Boot 3.5 为例:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:dryRun \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
说明:
参数
作用
rewrite-maven-plugin:6.41.0:dryRun
执行 dry-run,只生成变更预览
rewrite.recipeArtifactCoordinates
指定 Recipe 所在依赖包
rewrite.activeRecipes
指定要运行的 Recipe
rewrite.exportDatatables=true
导出迁移数据表
dryRun 不会直接改源码,它会在模块的 target 目录下生成 diff 结果。你可以先检查这些变更是否符合预期。
5.2 run:正式修改文件 确认 dry-run 没问题后,再正式执行:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
执行后查看变更:
1 2 git diff --stat git diff
然后跑测试:
如果是 Spring Boot 项目,可以进一步跑:
1 mvn clean package -DskipTests=false
确认没问题后提交:
1 2 git add . git commit -m "refactor: migrate project with OpenRewrite"
6. Maven 项目实战:把 OpenRewrite 配进 pom.xml 如果你希望团队长期使用 OpenRewrite,可以把插件加入根 pom.xml。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <build > <plugins > <plugin > <groupId > org.openrewrite.maven</groupId > <artifactId > rewrite-maven-plugin</artifactId > <version > 6.41.0</version > <configuration > <activeRecipes > <recipe > org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5</recipe > </activeRecipes > <exportDatatables > true</exportDatatables > <exclusions > <exclusion > **/target/**</exclusion > <exclusion > **/generated/**</exclusion > </exclusions > </configuration > <dependencies > <dependency > <groupId > org.openrewrite.recipe</groupId > <artifactId > rewrite-spring</artifactId > <version > 6.32.1</version > </dependency > </dependencies > </plugin > </plugins > </build >
然后可以直接执行:
1 2 mvn rewrite:dryRun mvn rewrite:run
常用 Maven goal:
Goal
说明
mvn rewrite:run
运行 Recipe,并直接修改本地文件
mvn rewrite:runNoFork
不 fork Maven 生命周期,适合部分 CI 场景
mvn rewrite:dryRun
只生成变更预览,不改文件
mvn rewrite:dryRunNoFork
不 fork 的 dry-run
mvn rewrite:discover
查看当前 classpath 下可用 Recipe
如果遇到:
1 No plugin found for prefix 'rewrite'
可以用完整坐标执行:
1 mvn org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run
7. Gradle 项目实战 7.1 直接配置 build.gradle Groovy DSL 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 plugins { id 'java' id 'org.openrewrite.rewrite' version '7.34.0' } repositories { mavenCentral() } rewrite { activeRecipe('org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5' ) exportDatatables = true } dependencies { rewrite('org.openrewrite.recipe:rewrite-spring:6.32.1' ) }
执行:
1 2 ./gradlew rewriteDryRun ./gradlew rewriteRun
7.2 不修改 build.gradle,用 init.gradle 临时执行 如果你只是想临时扫描一个 Gradle 项目,不想改业务仓库,可以创建 init.gradle:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 initscript { repositories { maven { url "https://plugins.gradle.org/m2" } } dependencies { classpath("org.openrewrite:plugin:7.34.0" ) } } rootProject { plugins.apply(org.openrewrite.gradle.RewritePlugin) repositories { mavenCentral() } dependencies { rewrite("org.openrewrite.recipe:rewrite-spring:6.32.1" ) } }
执行:
1 2 3 ./gradlew rewriteRun \ --init-script init.gradle \ -Drewrite.activeRecipe=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5
这种方式适合:
1 2 3 4 临时迁移 批量扫描多个项目 不想污染业务项目 build.gradle 企业统一工具仓库维护 init script
8. 实战案例一:Spring Boot 2.x 迁移到 Spring Boot 3.5 8.1 为什么 Spring Boot 3 迁移适合 OpenRewrite? Spring Boot 3 不是普通小版本升级,它涉及:
1 2 3 4 5 6 7 8 Java 17 baseline Spring Framework 6 Spring Security 6 Jakarta EE 迁移 Hibernate 6 配置属性变更 部分过时 API 移除 测试框架升级
其中大量修改是机械性的,非常适合 OpenRewrite。
8.2 迁移前检查 建议先做这些检查:
1 2 3 4 5 6 7 8 9 10 11 java -version mvn -version mvn clean test git checkout -b chore/migrate-spring-boot-3
如果当前项目连原版本都编译不过,不建议直接跑迁移。否则你分不清是历史问题还是迁移引入的问题。
8.3 执行 dryRun 1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:dryRun \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
8.4 正式执行 1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
8.5 典型代码变化 迁移前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import javax.servlet.http.HttpServletRequest;import javax.validation.Valid;import javax.persistence.Entity;@RestController @RequestMapping("/users") public class UserController { @PostMapping public Result create (@Valid @RequestBody UserCreateRequest request, HttpServletRequest servletRequest) { return Result.ok(); } }
迁移后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import jakarta.servlet.http.HttpServletRequest;import jakarta.validation.Valid;import jakarta.persistence.Entity;@RestController @RequestMapping("/users") public class UserController { @PostMapping public Result create (@Valid @RequestBody UserCreateRequest request, HttpServletRequest servletRequest) { return Result.ok(); } }
构建文件可能从:
1 2 3 4 5 6 7 8 9 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.7.18</version > </parent > <properties > <java.version > 11</java.version > </properties >
变成:
1 2 3 4 5 6 7 8 9 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 3.5.0</version > </parent > <properties > <java.version > 17</java.version > </properties >
8.6 迁移后必须人工检查的点 OpenRewrite 能处理很多机械变更,但不要幻想“一键飞升生产”。迁移后至少要检查:
检查项
说明
第三方依赖兼容性
老版本 starter、SDK、公司内部二方包可能不支持 Spring Boot 3
Spring Security 配置
Security 5 到 6 变化较多,复杂权限配置通常需要人工确认
MyBatis / JPA / Hibernate
SQL 行为、方言、懒加载、字段映射要回归测试
ShardingSphere / Dubbo / Nacos
需要确认对应版本是否支持 Boot 3 / JDK 17
配置属性
application.yml 里旧配置可能需要人工确认语义
自研框架
最容易炸,因为 OpenRewrite 不知道你们公司内部约定
建议迁移完成后执行:
1 2 3 4 5 mvn clean test mvn clean package mvn verify
再配合启动验证:
1 java -jar target/your-app.jar
9. 实战案例二:JUnit 4 迁移到 JUnit 5 JUnit 4 到 JUnit Jupiter 的迁移也很适合 OpenRewrite。
9.1 执行命令 1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-testing-frameworks:3.37.0 \ -Drewrite.activeRecipes=org.openrewrite.java.testing.junit5.JUnit4to5Migration \ -Drewrite.exportDatatables=true
9.2 典型变化 迁移前:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class) public class UserServiceTest { @Before public void setUp () { } @Test public void shouldCreateUser () { } }
迁移后:
1 2 3 4 5 6 7 8 9 10 11 12 13 import org.junit.jupiter.api.BeforeEach;import org.junit.jupiter.api.Test;class UserServiceTest { @BeforeEach void setUp () { } @Test void shouldCreateUser () { } }
9.3 只迁移 @Test 注解 如果你只想小步迁移,可以只跑更小的 Recipe:
1 2 3 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-testing-frameworks:3.37.0 \ -Drewrite.activeRecipes=org.openrewrite.java.testing.junit5.UpdateTestAnnotation
10. 实战案例三:Java 8 / 11 升级到 Java 17 或 21 Java 版本升级常见问题包括:
1 2 3 4 5 JDK 内置模块移除 旧 API 废弃 Maven 编译插件版本过老 surefire / failsafe 插件版本不兼容 老依赖不兼容新 JDK
Java 17 迁移:
1 2 3 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:3.36.0 \ -Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava17
Java 21 迁移:
1 2 3 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:3.36.0 \ -Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava21
迁移后建议至少跑:
1 2 mvn clean test mvn clean package
如果项目里用了 Lombok、MapStruct、QueryDSL、JPA Metamodel、MyBatis Generator 等生成代码工具,要特别注意 annotation processor 的版本。
11. 实战案例四:Maven 依赖治理 OpenRewrite 不只是改 Java 代码,也可以改 Maven 构建文件。
11.1 自定义 rewrite.yml 在项目根目录创建 rewrite.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 type: specs.openrewrite.org/v1beta/recipe name: com.cybersupermario.UpgradeCommonDependencies displayName: Upgrade common Maven dependencies description: 统一升级公司常用基础依赖版本。 recipeList: - org.openrewrite.maven.UpgradeDependencyVersion: groupId: org.apache.commons artifactId: commons-lang3 newVersion: 3. x - org.openrewrite.maven.UpgradeDependencyVersion: groupId: com.google.guava artifactId: guava newVersion: 33. x
执行:
1 2 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.activeRecipes=com.cybersupermario.UpgradeCommonDependencies
11.2 添加依赖 1 2 3 4 5 6 7 8 type: specs.openrewrite.org/v1beta/recipe name: com.cybersupermario.AddMapStruct displayName: Add MapStruct dependency recipeList: - org.openrewrite.maven.AddDependency: groupId: org.mapstruct artifactId: mapstruct version: 1.6 .x
11.3 删除依赖 1 2 3 4 5 6 7 type: specs.openrewrite.org/v1beta/recipe name: com.cybersupermario.RemoveOldDependency displayName: Remove old dependency recipeList: - org.openrewrite.maven.RemoveDependency: groupId: commons-logging artifactId: commons-logging
这个场景适合企业统一治理,比如:
1 2 3 4 5 统一升级 commons-lang3 清理老的 commons-logging 替换旧版 fastjson 统一 Maven Compiler Plugin 版本 统一 Surefire Plugin 版本
12. 实战案例五:查找项目里的特定代码模式 OpenRewrite 也可以只做“搜索”,不做修改。
比如你想查找所有 Spring 相关方法调用,可以创建:
1 2 3 4 5 6 7 type: specs.openrewrite.org/v1beta/recipe name: com.cybersupermario.FindSpringUses displayName: Find all Spring uses description: 查找项目中对 Spring API 的使用。 recipeList: - org.openrewrite.java.search.FindMethods: methodPattern: org.springframework..* *(..)
执行:
1 2 3 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:dryRun \ -Drewrite.activeRecipes=com.cybersupermario.FindSpringUses \ -Drewrite.exportDatatables=true
这适合做迁移前评估:
1 2 3 4 项目用了多少 Spring API? 哪些模块用了 javax? 哪些地方用了过时工具类? 哪些服务需要优先迁移?
13. 和 CI/CD 结合 13.1 GitLab CI dry-run 示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 stages: - rewrite - test openrewrite-dryrun: stage: rewrite image: maven:3.9-eclipse-temurin-21 script: - mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:dryRun -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 -Drewrite.exportDatatables=true -Drewrite.failOnDryRunResults=true artifacts: when: always paths: - "**/target/**" expire_in: 7 days
这个配置可以用于检查:当前分支如果执行迁移,是否还有未应用的重构结果。
13.2 手动创建迁移 MR 更推荐的企业做法是:
1 2 3 4 5 6 7 8 9 10 11 12 git checkout -b chore/openrewrite-spring-boot-3 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true mvn clean test git add . git commit -m "refactor: migrate to Spring Boot 3.5 with OpenRewrite" git push origin chore/openrewrite-spring-boot-3
然后在 GitLab / GitHub 创建 MR / PR。
不要一上来就做“全自动合并”,迁移类变更还是要人工 review。自动化不是放飞自我,CI 也不是许愿池。
14. 和 Renovate 配合的企业依赖治理方案 一个比较成熟的治理流程可以这样设计:
flowchart TB
A[Renovate 定期扫描依赖] --> B[提交依赖升级 MR]
B --> C[CI 触发 OpenRewrite dryRun]
C --> D{是否存在可自动迁移变更}
D -->|有| E[人工或机器人执行 OpenRewrite run]
D -->|无| F[直接跑测试]
E --> G[提交迁移 commit]
F --> H[单测/集成测试/扫描]
G --> H
H --> I[Code Review]
I --> J[合并]
推荐策略:
依赖类型
建议策略
patch 版本
Renovate 自动提 MR,CI 通过后可半自动合并
minor 版本
分组提 MR,跑完整测试
major 版本
必须人工审批,必要时配合 OpenRewrite
Spring Boot / Spring Cloud
单独分组,不要和普通依赖混在一起
JDK 升级
单独迁移项目,先跑 OpenRewrite,再人工验证
15. 私服 / Nexus / 企业内网注意事项 OpenRewrite 运行时需要解析项目依赖和 Recipe 依赖。如果公司网络无法直接访问 Maven Central,就要配置 Maven settings.xml,让它走 Nexus / Artifactory。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <settings > <mirrors > <mirror > <id > company-nexus</id > <mirrorOf > *</mirrorOf > <url > https://nexus.example.com/repository/maven-public/</url > </mirror > </mirrors > <servers > <server > <id > company-nexus</id > <username > ${env.NEXUS_USERNAME}</username > <password > ${env.NEXUS_PASSWORD}</password > </server > </servers > </settings >
运行前设置环境变量:
1 2 export NEXUS_USERNAME=renovateexport NEXUS_PASSWORD=your-password
如果企业 Nexus 没代理 OpenRewrite 相关依赖,常见表现是:
1 2 Could not find artifact org.openrewrite.recipe:rewrite-spring Could not resolve plugin org.openrewrite.maven:rewrite-maven-plugin
解决思路:
1 2 3 4 1. 让 Nexus 代理 Maven Central; 2. 确认 rewrite-maven-plugin、rewrite-spring、rewrite-testing-frameworks 等依赖能下载; 3. CI 镜像里配置统一 settings.xml; 4. 不要把账号密码写进仓库。
16. 常见问题排查 16.1 Recipe not found 表现:
原因通常是没有引入对应 Recipe 包。
比如 Spring Boot 迁移需要:
1 org.openrewrite.recipe:rewrite-spring
JUnit 迁移需要:
1 org.openrewrite.recipe:rewrite-testing-frameworks
Java 版本迁移需要:
1 org.openrewrite.recipe:rewrite-migrate-java
16.2 没有任何代码变化 可能原因:
1 2 3 4 5 1. activeRecipes 写错; 2. 当前代码本来就不匹配该 Recipe; 3. 项目依赖解析失败,类型信息不完整; 4. 代码在 exclusions 里被排除了; 5. 多模块项目只在子模块跑了,没在根目录跑。
可以先执行:
查看当前可用的 Recipe。
16.3 内存不够 大项目可能需要加内存:
1 export MAVEN_OPTS="-Xmx4g -XX:+UseG1GC"
然后再执行 OpenRewrite。
16.4 多模块项目怎么跑? Maven 多模块项目建议在根 pom.xml 所在目录执行。
1 2 3 4 cd your-root-project mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5
Gradle 多模块项目建议把 plugin 应用到 root project。OpenRewrite Gradle 插件应用在根项目时,会解析和重构所有子项目源码。
16.5 OpenRewrite 能不能完全替代人工? 不能。
它擅长处理:
1 2 3 4 5 机械性变更 标准 API 迁移 依赖版本治理 配置属性调整 大量重复代码修改
但它不能完全理解:
1 2 3 4 你的业务语义 你的公司自研框架 你的历史脏数据兼容逻辑 你的线上运行约束
所以正确姿势是:
1 2 3 4 OpenRewrite 负责批量机械迁移; 开发者负责业务语义确认; CI 负责自动验证; Review 负责最终把关。
17. 推荐落地路线 如果你准备在团队里引入 OpenRewrite,可以按这个节奏来:
第一阶段:本地试跑 1 2 3 4 5 6 选一个小项目 新建分支 跑 dryRun 看 diff 跑 run 跑测试
第二阶段:单服务迁移 1 2 3 4 5 选一个非核心服务 只跑一个 Recipe 提交 MR 让团队熟悉 review 方式 总结迁移问题清单
第三阶段:标准化配置 1 2 3 4 沉淀 rewrite.yml 沉淀 Maven / Gradle 执行脚本 沉淀 CI 模板 沉淀私服 settings.xml
第四阶段:多服务推广 1 2 3 4 按服务等级分批迁移 先低风险服务 再核心服务 每批保留回滚方案
第五阶段:和 Renovate / CI 联动 1 2 3 4 Renovate 负责发现升级机会 OpenRewrite 负责自动迁移代码 CI 负责验证 人工负责合并
18. 一个完整操作清单 假设你现在有一个 Maven + Spring Boot 2.7 项目,要迁移到 Spring Boot 3.5,可以直接按这个清单操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 git status mvn clean test git checkout -b chore/migrate-spring-boot-3 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:dryRun \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true git diff --stat git diff mvn clean test mvn clean package git add . git commit -m "refactor: migrate to Spring Boot 3.5 with OpenRewrite" git push origin chore/migrate-spring-boot-3
19. 小结 OpenRewrite 的价值不是“炫技”,而是把大规模迁移从手工劳动变成工程化流程。
它特别适合:
1 2 3 4 5 6 老项目升级 JDK Spring Boot 2 升级 Spring Boot 3 JUnit 4 迁移 JUnit 5 统一 Maven 依赖治理 批量删除过时代码 配合 Renovate 做依赖升级闭环
但也要记住:OpenRewrite 是自动化迁移工具,不是魔法棒。
正确用法是:
1 2 3 4 5 6 先 dryRun 再 run 看 diff 跑测试 人工 review 小步提交
只要流程设计得好,它可以把“几天到几周的机械迁移”压缩成“几个小时内完成初稿”,剩下时间留给真正需要人脑判断的部分。
参考资料
OpenRewrite 官方文档:https://docs.openrewrite.org/
OpenRewrite Maven Plugin:https://docs.openrewrite.org/reference/rewrite-maven-plugin
OpenRewrite Gradle Plugin:https://docs.openrewrite.org/reference/gradle-plugin-configuration
OpenRewrite 最新版本列表:https://docs.openrewrite.org/reference/latest-versions-of-every-openrewrite-module
Spring Boot 3 迁移指南:https://docs.openrewrite.org/running-recipes/popular-recipe-guides/migrate-to-spring-3
Spring Boot 3.5 Recipe:https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot_3_5-community-edition
JUnit 4 到 JUnit 5 迁移:https://docs.openrewrite.org/running-recipes/popular-recipe-guides/migrate-from-junit-4-to-junit-5
Java 17 迁移 Recipe:https://docs.openrewrite.org/recipes/java/migrate/upgradetojava17
Maven 依赖升级 Recipe:https://docs.openrewrite.org/recipes/maven/upgradedependencyversion
Maven 项目不修改构建文件运行 OpenRewrite:https://docs.openrewrite.org/running-recipes/running-rewrite-on-a-maven-project-without-modifying-the-build
Gradle 项目不修改构建文件运行 OpenRewrite:https://docs.openrewrite.org/running-recipes/running-rewrite-on-a-gradle-project-without-modifying-the-build
启示录 工具真正的价值,不是替你写代码,而是把重复、机械、容易出错的事情变成可验证的工程流程。
能自动化的地方就自动化,不能自动化的地方就沉淀规则;技术债不是一天形成的,也别指望一天还清。