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

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

问题描述

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

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

我有一个领域.如果在此字段中输入了某个值,我想要求其他一些字段不是 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 a 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)
@Repeatable(NotNullIfAnotherFieldHasValue.List.class) // only with hibernate-validator >= 6.x
@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;
        }
    
    }
    

  • 验证器使用示例(hibernate-validator >= 6 with Java 8+)

  • Validator usage example (hibernate-validator >= 6 with Java 8+)

    @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
    }
    

  • Validator 使用示例(hibernate-validator <6; 旧示例)

  • Validator usage example (hibernate-validator < 6; the old 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 类,但您也可以使用 BeanWrapperImpl 来自 Spring 框架.

    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天全站免登陆