Java 创建运行时约束并验证字段映射

Java 创建运行时约束并验证字段映射,java,bean-validation,hibernate-validator,Java,Bean Validation,Hibernate Validator,我有一个输入字段的映射,我想通过在运行时创建动态约束来使用JSR-303验证它 假设我的地图的结构如下所示: name: Foo description: Foo description 现在,如果我有一组存储在某种配置中的规则,它说: name: required: true minLength: 3 maxLength: 30 description: required: false maxLength: 200 我想使用在运行时根据上述配置创

我有一个输入字段的映射,我想通过在运行时创建动态约束来使用JSR-303验证它

假设我的地图的结构如下所示:

name: Foo
description: Foo description
现在,如果我有一组存储在某种配置中的规则,它说:

name:
    required: true
    minLength: 3
    maxLength: 30

description:
    required: false
    maxLength: 200

我想使用在运行时根据上述配置创建的约束来验证我的输入映射。我知道我们可以这样做(示例取自Hibernate Validator文档):

HibernateValidatorConfiguration配置=验证
.byProvider(HibernateValidator.class)
.configure();
ConstraintMapping ConstraintMapping=configuration.createConstraintMapping();
约束映射
.类型(汽车.等级)
.属性(“制造商”,字段)
.constraint(新的NotNullDef())
.物业(“许可证牌”,字段)
.ignoreAnnotations(true)
.constraint(新的NotNullDef())
.constraint(新的SizeDef().min(2).max(14))
Validator Validator=configuration.addMapping(constraintMapping)
.buildValidatorFactory()
但显然,这对
java.util.Map
s不起作用,因为映射不是JavaBeans。那么我该怎么做呢?我考虑了一些事情(每种方法的缺点):

  • 在运行时使用ByteBuddy或类似工具创建类,并使用Hibernate Validator进行验证(听起来有点过头了)
  • 使用一系列
    if
    条件手动验证,并抛出
    ConstraintViolationException
    (我将在这里重新设计很多轮子)

  • 我想知道在这种情况下你会怎么做。

    有太多的问题要回答,但我会尽力回答

    动态创建的约束映射 正如示例所描述的,它是可用的。有两种方法可以创建自定义映射

    以编程方式创建自定义约束映射 让我们假设有一个POJO

    import java.util.Map;
    公开课Foo{
    私有地图规则;
    公共映射getRules(){
    退货规则;
    }
    公共无效集合规则(映射规则){
    这个。规则=规则;
    }
    }
    
    所描述的约束是:

    • 地图不能为空
    • 地图的最大尺寸为2
    • 地图的键应至少为3个字符
    • 值不能为空,并且
    • 值必须最大为5个字符
    像这样:

    @NotNull
    @尺寸(最大值=3)
    私有地图规则;
    
    其约束映射为:

    var配置=验证
    .byProvider(HibernateValidator.class)
    .configure();
    ConstraintMapping ConstraintMapping=configuration.createConstraintMapping();
    约束映射
    .type(Foo.class)
    .字段(“规则”)
    .constraint(新的NotNullDef())
    .constraint(新的SizeDef().max(2))
    .containerElementType(0)
    .constraint(新的SizeDef().min(3))
    .containerElementType(1)
    .constraint(新的NotBlankDef())
    .constraint(新的SizeDef().max(5))
    ;
    var validator=configuration.addMapping(constraintMapping)
    .buildValidatorFactory()
    .getValidator();
    
    例如:

    公共类测试{
    @试验
    无效名称(){
    var配置=验证
    .byProvider(HibernateValidator.class)
    .configure();
    ConstraintMapping ConstraintMapping=configuration.createConstraintMapping();
    约束映射
    .type(Foo.class)
    .字段(“规则”)
    .constraint(新的NotNullDef())
    .constraint(新的SizeDef().max(2))
    .containerElementType(0)
    .constraint(新的SizeDef().min(3))
    .containerElementType(1)
    .constraint(新的NotBlankDef())
    .constraint(新的SizeDef().max(5))
    ;
    var validator=configuration.addMapping(constraintMapping)
    .buildValidatorFactory()
    .getValidator();
    资产(
    () -> {
    var obj=新的Foo();
    /*
    预期的违规行为
    映射为空
    */
    var result=validator.validate(obj.stream().toList();
    assertAll(“仅应违反@NotNull”,
    ()->assertEquals(1,result.size()),
    ()->assertEquals({jakarta.validation.constraints.NotNull.message}),
    result.get(0).getMessageTemplate()
    )
    );
    },
    () -> {
    var obj=新的Foo();
    /*
    预期的违规行为
    地图包含的元素太多(最多:2个)
    注意:键和值未经验证
    */
    对象设置规则(映射(“名称1”、“描述1”、“名称2”、“描述2”、“名称3”、“描述3”));
    var result=validator.validate(obj.stream().toList();
    assertAll(“仅应违反@Size”,
    ()->assertEquals(1,result.size()),
    ()->assertEquals({jakarta.validation.constraints.Size.message}),
    result.get(0).getMessageTemplate()
    )
    );
    },
    () -> {
    var obj=新的Foo();
    /*
    预期的违规行为
    第一个键太短(最小值:3)
    第一个值为空
    第二个值太长(最大值:5)
    */
    对象设置规则(映射“aa”、“bbb”、“longValue”);
    var result=validator.validate