如何用ArchUnit实现敏感变量名的黑名单校验?
解决方案
1. 字段/Record组件的命名校验
ArchUnit本身具备直接校验字段名称和类型的能力,完全可以实现场景a的需求,无需等待新版本:
针对UUID类型字段的精准校验
@ArchTest ArchRule uuid_field_naming_rule = fields() .that().haveRawType(UUID.class) .and().haveName("uuid") .should().be().violated();
灵活的黑名单术语校验
针对场景b的废弃术语需求,可以通过正则匹配实现批量拦截:
// 定义黑名单术语列表 private static final List<String> FORBIDDEN_FIELD_NAMES = List.of("uuid", "oldUserTerm", "deprecatedOrderCode"); @ArchTest ArchRule forbidden_field_naming_rule = fields() .that().haveNameMatching(String.join("|", FORBIDDEN_FIELD_NAMES)) .should().be().violated();
Record的组件会被ArchUnit视为字段处理,上述规则完全适用。
2. 局部变量的命名校验
若需校验方法内的局部变量名,ArchUnit 1.0.0-rc1无直接API,但可结合ASM(ArchUnit已内置依赖)扩展实现:
自定义ArchUnit条件
public class ForbiddenLocalVariableCondition extends ArchCondition<JavaMethod> { private final Set<String> forbiddenNames; public ForbiddenLocalVariableCondition(Set<String> forbiddenNames) { super("not contain forbidden local variable names: " + forbiddenNames); this.forbiddenNames = forbiddenNames; } @Override public void check(JavaMethod method, ConditionEvents events) { method.getMethod().accept(new ClassVisitor(Opcodes.ASM9) { @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { return new MethodVisitor(Opcodes.ASM9) { @Override public void visitLocalVariable(String varName, String desc, String signature, Label start, Label end, int index) { if (forbiddenNames.contains(varName)) { String message = String.format("Method %s contains forbidden local variable name: %s", method.getFullName(), varName); events.add(SimpleConditionEvent.violated(method, message)); } super.visitLocalVariable(varName, desc, signature, start, end, index); } }; } }); } }
在测试中使用自定义条件
@ArchTest ArchRule forbidden_local_variables_rule = methods() .should(new ForbiddenLocalVariableCondition(Set.of("uuid", "oldTempVar")));
3. 方法参数的命名校验
若需校验方法参数名称,需确保编译时保留参数名(Maven/Gradle中开启-parameters编译选项),然后通过ArchUnit的参数API实现:
@ArchTest ArchRule forbidden_parameter_names_rule = methods() .flatMap(method -> method.getParameters().stream()) .that().haveNameMatching("uuid|oldParamName") .should().be().violated();
内容的提问来源于stack exchange,提问作者d.braun1991
相关产品推荐
相关产品推荐

