如何在OpenRewrite中替换类常量的静态导入(含类与常量名变更)
使用OpenRewrite批量替换静态导入的类常量(类类型+常量名同步变更)
需要将代码中静态导入的javax.ws.rs.core.MediaType.APPLICATION_JSON替换为org.springframework.http.MediaType.APPLICATION_JSON_VALUE,包含两个核心变更:
- 类类型从
javax.ws.rs.core.MediaType改为org.springframework.http.MediaType - 常量名从
APPLICATION_JSON改为APPLICATION_JSON_VALUE
原始代码示例:
import javax.ws.rs.*; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; class ControllerClass { @Produces(APPLICATION_JSON) public String getHelloWorldJSON(String name) { return "{}"; } }
期望代码示例:
import javax.ws.rs.*; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; class ControllerClass { @Produces(APPLICATION_JSON_VALUE) public String getHelloWorldJSON(String name) { return "{}"; } }
单独使用OpenRewrite的ChangeType仅能替换类类型,无法同步修改常量名,需通过组合内置Recipe实现完整替换。
解决方案:组合ChangeStaticImport与ChangeFieldReference Recipe
可以通过YAML配置直接组合内置Recipe,或封装为自定义Java Recipe,两种方式均支持大型代码库批量迁移:
方式1:YAML配置组合(适合OpenRewrite插件直接调用)
type: specs.openrewrite.org/v1beta/recipe name: com.example.ReplaceMediaTypeConstant displayName: 替换JAX-RS MediaType常量为Spring MediaType常量 description: 将javax.ws.rs.core.MediaType.APPLICATION_JSON替换为org.springframework.http.MediaType.APPLICATION_JSON_VALUE recipeList: - org.openrewrite.java.ChangeStaticImport: oldFullyQualifiedTypeName: javax.ws.rs.core.MediaType oldMemberName: APPLICATION_JSON newFullyQualifiedTypeName: org.springframework.http.MediaType newMemberName: APPLICATION_JSON_VALUE - org.openrewrite.java.ChangeFieldReference: oldFieldName: APPLICATION_JSON oldOwnerType: javax.ws.rs.core.MediaType newFieldName: APPLICATION_JSON_VALUE newOwnerType: org.springframework.http.MediaType
方式2:Java自定义CompositeRecipe(适合扩展复杂逻辑)
package com.example; import org.openrewrite.ExecutionContext; import org.openrewrite.Recipe; import org.openrewrite.java.ChangeFieldReference; import org.openrewrite.java.ChangeStaticImport; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.tree.J; public class ReplaceMediaTypeConstant extends Recipe { @Override public String getDisplayName() { return "替换JAX-RS MediaType常量为Spring MediaType常量"; } @Override public String getDescription() { return "将javax.ws.rs.core.MediaType.APPLICATION_JSON替换为org.springframework.http.MediaType.APPLICATION_JSON_VALUE"; } @Override protected JavaIsoVisitor<ExecutionContext> getVisitor() { return new JavaIsoVisitor<ExecutionContext>() { @Override public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) { // 替换静态导入语句 doAfterVisit(new ChangeStaticImport( "javax.ws.rs.core.MediaType", "APPLICATION_JSON", "org.springframework.http.MediaType", "APPLICATION_JSON_VALUE" ).getVisitor()); // 替换代码中所有常量引用(包括注解参数) doAfterVisit(new ChangeFieldReference( "javax.ws.rs.core.MediaType", "APPLICATION_JSON", "org.springframework.http.MediaType", "APPLICATION_JSON_VALUE" ).getVisitor()); return super.visitCompilationUnit(cu, ctx); } }; } }
核心逻辑说明
ChangeStaticImport:专门处理静态导入语句,精准替换原类常量的导入路径为目标类的目标常量导入ChangeFieldReference:遍历代码中所有引用该常量的位置(包括注解参数、变量赋值等),同步替换常量名与所属类- 两个Recipe组合执行,可确保静态导入和代码引用的一致性替换,满足大型迁移的批量处理需求
内容的提问来源于stack exchange,提问作者Vincent Botteman
相关产品推荐
相关产品推荐

