JSR 303验证,如果一个字段等于“某事物”,那么这些其他字段不应为空 [英] JSR 303 Validation, If one field equals "something", then these other fields should not be null

查看:163
本文介绍了JSR 303验证,如果一个字段等于“某事物”,那么这些其他字段不应为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望用JSR-303进行一些自定义验证 javax.validation

I'm looking to do a little custom validation with JSR-303 javax.validation.

I有一个领域。如果在此字段中输入了某个值,我想要求其他几个字段不是 null

I have a field. And If a certain value is entered into this field I want to require that a few other fields are not null.

我想弄明白这一点。不确定我会称之为什么来帮助找到解释。

I'm trying to figure this out. Not sure exactly what I would call this to help find an explanation.

任何帮助将不胜感激。我对此很新。

Any help would be appreciated. I am pretty new to this.

目前我正在考虑自定义约束。但我不确定如何从注释中测试依赖字段的值。基本上我不确定如何从注释中访问面板对象。

At the moment I'm thinking a Custom Constraint. But I'm not sure how to test the value of the dependent field from within the annotation. Basically I'm not sure how to access the panel object from the annotation.

public class StatusValidator implements ConstraintValidator<NotNull, String> {

    @Override
    public void initialize(NotNull constraintAnnotation) {}

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if ("Canceled".equals(panel.status.getValue())) {
            if (value != null) {
                return true;
            }
        } else {
            return false;
        }
    }
}

这是 panel.status.getValue(); 给我带来麻烦..不知道如何做到这一点。

It's the panel.status.getValue(); giving me trouble.. not sure how to accomplish this.

推荐答案

在这种情况下,我建议编写自定义验证器,它将在类级别验证(允许我们访问对象的字段),只有当另一个字段具有特定值时才需要一个字段。请注意,您应该编写通用验证器,它获取2个字段名称并仅使用这2个字段。要要求多个字段,您应该为每个字段添加此验证器。

In this case I suggest to write custom validator, which will validate at class level (to allow us get access to object's fields) that one field is required only if another field has particular value. Note that you should write generic validator which gets 2 field names and work with only these 2 fields. To require more than one field you should add this validator for each field.

使用以下代码作为一个想法(我没有测试它)。

Use the following code as an idea (I've not test it).


  • 验证器界面

  • Validator interface

/**
 * Validates that field {@code dependFieldName} is not null if
 * field {@code fieldName} has value {@code fieldValue}.
 **/
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = NotNullIfAnotherFieldHasValueValidator.class)
@Documented
public @interface NotNullIfAnotherFieldHasValue {

    String fieldName();
    String fieldValue();
    String dependFieldName();

    String message() default "{NotNullIfAnotherFieldHasValue.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
    @interface List {
        NotNullIfAnotherFieldHasValue[] value();
    }

}


  • 验证器实施

  • Validator implementation

    /**
     * Implementation of {@link NotNullIfAnotherFieldHasValue} validator.
     **/
    public class NotNullIfAnotherFieldHasValueValidator
        implements ConstraintValidator<NotNullIfAnotherFieldHasValue, Object> {
    
        private String fieldName;
        private String expectedFieldValue;
        private String dependFieldName;
    
        @Override
        public void initialize(NotNullIfAnotherFieldHasValue annotation) {
            fieldName          = annotation.fieldName();
            expectedFieldValue = annotation.fieldValue();
            dependFieldName    = annotation.dependFieldName();
        }
    
        @Override
        public boolean isValid(Object value, ConstraintValidatorContext ctx) {
    
            if (value == null) {
                return true;
            }
    
            try {
                String fieldValue       = BeanUtils.getProperty(value, fieldName);
                String dependFieldValue = BeanUtils.getProperty(value, dependFieldName);
    
                if (expectedFieldValue.equals(fieldValue) && dependFieldValue == null) {
                    ctx.disableDefaultConstraintViolation();
                    ctx.buildConstraintViolationWithTemplate(ctx.getDefaultConstraintMessageTemplate())
                        .addNode(dependFieldName)
                        .addConstraintViolation();
                        return false;
                }
    
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
                throw new RuntimeException(ex);
            }
    
            return true;
        }
    
    }
    


  • Validator用法示例

  • Validator usage example

    @NotNullIfAnotherFieldHasValue.List({
        @NotNullIfAnotherFieldHasValue(
            fieldName = "status",
            fieldValue = "Canceled",
            dependFieldName = "fieldOne"),
        @NotNullIfAnotherFieldHasValue(
            fieldName = "status",
            fieldValue = "Canceled",
            dependFieldName = "fieldTwo")
    })
    public class SampleBean {
        private String status;
        private String fieldOne;
        private String fieldTwo;
    
        // getters and setters omitted
    }
    


  • 请注意,验证器实现使用 commons-beanutils 库中的 BeanUtils 类,但是你也可以使用 <$来自Spring Framework的c $ c> BeanWrapperImpl 。

    Note that validator implementation uses BeanUtils class from commons-beanutils library but you could also use BeanWrapperImpl from Spring Framework.

    另见这个好答案:使用Hibernate Validator(JSR 303)进行跨领域验证

    这篇关于JSR 303验证,如果一个字段等于“某事物”,那么这些其他字段不应为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆