Lambda表达式构建可插拔校验规则库,通过泛型函数式接口+双键注册中心实现类型安全、动态组合与上下文解耦。

用 Lambda 表达式构建可插拔的业务校验规则库,核心是把“验证逻辑”变成可动态注册、组合和执行的一等公民。变量验证不再硬编码在业务流程里,而是通过函数式接口 + Map/Registry 管理规则,实现高内聚、低耦合。
定义统一的校验函数接口
Java 中推荐使用 Function<T, ValidationResult> 或自定义函数式接口,比 Predicate 更灵活(能返回详细错误信息):
@FunctionalInterface
public interface Validator<T> {
ValidationResult validate(T value);
}
// ValidationResult 封装是否通过、错误码、提示语等
这样每个校验规则就是一个 Lambda 实例,例如:
Validator<String> notBlank = s ->
StringUtils.isBlank(s)
? new ValidationResult(false, "不能为空")
: ValidationResult.success();
Validator<Integer> positive = i ->
i == null || i <= 0
? new ValidationResult(false, "必须为正整数")
: ValidationResult.success();
用 Registry 管理可插拔规则
避免 if-else 或 switch 分支,用 Map 按“业务场景+字段名”或“规则 ID”索引规则:
public class ValidationRegistry {
private final Map<String, Validator<?>> registry = new ConcurrentHashMap<>();
public <T> void register(String ruleId, Validator<T> validator) {
registry.put(ruleId, validator);
}
@SuppressWarnings("unchecked")
public <T> ValidationResult validate(String ruleId, T value) {
Validator<T> validator = (Validator<T>) registry.get(ruleId);
return validator != null ? validator.validate(value) : ValidationResult.success();
}
}
使用时可动态加载:
- 启动时扫描 @ValidateRule 注解的 Bean 自动注册
- 从配置中心拉取规则脚本(配合 Groovy/Janino 编译为 Lambda)
- 运行时通过 API 注册新规则(如运营后台配置手机号格式校验)
组合多个规则做链式验证
Lambda 天然支持函数组合。扩展 Validator 接口,添加 andThen 方法:
default Validator<T> andThen(Validator<T> after) {
return t -> {
ValidationResult r1 = this.validate(t);
if (!r1.isSuccess()) return r1;
return after.validate(t);
};
}
轻松组装规则:
Validator<String> mobileValidator = notBlank.andThen(formatMobile).andThen(inBlacklist);
ValidationResult result = mobileValidator.validate("13800138000");
结合泛型与类型擦除规避强制转换
上面 registry 的 > 带来类型不安全。更健壮的做法是按 Class<T> + 规则名双键管理:
private final Map<Class<?>, Map<String, Validator<?>>> typeBasedRegistry = new ConcurrentHashMap<>();
public <T> void register(Class<T> type, String ruleId, Validator<T> validator) {
typeBasedRegistry.computeIfAbsent(type, k -> new ConcurrentHashMap<>())
.put(ruleId, validator);
}
@SuppressWarnings("unchecked")
public <T> ValidationResult validate(Class<T> type, String ruleId, T value) {
Map<String, Validator<?>> rules = typeBasedRegistry.get(type);
Validator<T> validator = rules == null ? null : (Validator<T>) rules.get(ruleId);
return validator != null ? validator.validate(value) : ValidationResult.success();
}
调用时明确传入类型:registry.validate(String.class, "mobile", phone),安全且清晰。
不复杂但容易忽略:Lambda 是状态无关的纯函数,规则本身不应持有上下文(如用户会话)。需要访问上下文的校验,应封装成 Supplier<Validator<T>> 或引入 Context 参数,保持规则可测试、可复用。

















