Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何有条件地调用spring验证器_Java_Spring_Validation - Fatal编程技术网

Java 如何有条件地调用spring验证器

Java 如何有条件地调用spring验证器,java,spring,validation,Java,Spring,Validation,我有一个像下面这样的模型。现有代码已经对单个属性进行了验证。现在我有一个要求,如果买家,则忽略对账单国家和地址的现有验证。方法是foo。我想我可以有一个buyer级别的自定义验证器,只在buyer.method=foo。这是一种有效的方法吗?还有更好的选择吗 "buyer": { "method": "foo", "instruments": [ { "card": { "type": "MASTERCARD",

我有一个像下面这样的模型。现有代码已经对单个属性进行了验证。现在我有一个要求,如果
买家,则忽略对账单国家和地址的现有验证。方法
foo
。我想我可以有一个
buyer
级别的自定义验证器,只在
buyer.method=foo
。这是一种有效的方法吗?还有更好的选择吗

"buyer": {
    "method": "foo",
    "instruments": [
      {
        "card": {
          "type": "MASTERCARD",
          "number": "234234234234234",
          "expire_month": "12",
          "expire_year": "2017",
          "billing_country" : "US"
          "Address" : {
             "line1": "summer st",
             "city": "Boston"
             "country": "US"
           }
        }
      }
    ]
}

有两种方法可以做到这一点

你也可以

  • 创建一个自定义验证注释和验证器,用于检查
    方法的值,然后将相应的验证应用于其他字段

  • 使用,手动检查
    方法的值,然后选择要使用的组;然后,需要将带注释的字段更改为仅在该组处于活动状态时应用

  • 选项#1

    定义类级注释:

    @Target({ TYPE, ANNOTATION_TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = { MethodAndInstrumentsValidator.class })
    @Documented
    public @interface ValidMethodAndInstruments {
        String message() default "{my.package.MethodAndInstruments.message}";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }
    
    选项2

    在这里,您必须手动调用验证

    首先,定义验证组:

    public interface FooValidation {}
    public interface NotFooValidation {}
    
    配置验证器:

    public class MethodAndInstrumentsValidator 
                 implements ConstraintValidator<ValidMethodAndInstruments, Buyer> {
        public final void initialize(final ValidMethodAndInstruments annotation) {
            // setup
        }
    
        public final boolean isValid(final Buyer value, 
                                     final ConstraintValidatorContext context) {
            // validation logic
            if(!"foo".equals(value.getMethod())) {
                // do whatever conditional validation you want
            }
        }
    
    }
    
    @Bean
    public LocalValidatorFactoryBean validatorFactory() {
        return new LocalValidatorFactoryBean();
    }
    
    在控制器(?)中,检查
    方法的值
    ,并执行验证:

    @Autowired
    private Validator validator;
    
    // ...
    
    public void validate(Object a, Class<?>... groups) {
        Set<ConstraintViolation<Object>> violations = validator.validate(a, groups);
        if(!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
    }
    
    // ...
    
    validate(buyer, "foo".equals(buyer.getMethod()) 
                        ? FooValidation.class 
                        : NotFooValidation.class);
    

    @比尔巴杰的回答在某种程度上有所帮助,所以我将接受他的回答。然而,我还想记下我们在这个方法中遇到的几个问题。我们无法对地址使用
    @Null
    @NotNull
    注释,因为它可能为Null。其次,由于我们必须将其包装在自定义约束验证器中,因此对于
    notfoovalization.class
    ,我们得到了不需要的额外验证消息字符串。最后,我们无法使用
    @Valid
    中的组,该组已存在于
    地址中。我们尝试了
    @验证
    ,但由于某种原因,没有成功。我们最终实现了
    ReaderInterceptor
    来拦截请求并手动调用所需的验证。希望这对以后的人有所帮助

    @Autowired
    private Validator validator;
    
    // ...
    
    public void validate(Object a, Class<?>... groups) {
        Set<ConstraintViolation<Object>> violations = validator.validate(a, groups);
        if(!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
    }
    
    // ...
    
    validate(buyer, "foo".equals(buyer.getMethod()) 
                        ? FooValidation.class 
                        : NotFooValidation.class);
    
    public class Buyer {
        // ...
    
        @Null(groups = FooValidation.class)
        @NotNull(groups = NotFooValidation.class)
        protected String billingCountry;
    }