JSR 303validation,如果一个字段等于“东西”,那么这些其他字段不应该为空

我正在使用JSR-303 javax.validation进行一些自定义validation。

我有一个领域。 如果某个值input到这个字段中,我想要求其他字段不为null

我试图弄清楚这一点。 不确定我会怎么称呼这个来帮助find解释。

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

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

 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(); 给我麻烦..不知道如何做到这一点。

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

使用下面的代码作为一个想法(我没有testing它)。

  • validation器界面

     /** * 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(); } } 
  • validation器实现

     /** * 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; } } 
  • validation器使用示例

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

请注意,validation器实现使用来自commons-beanutils库的BeanUtils类,但是您也可以使用Spring框架中的BeanWrapperImpl

另请参阅此优秀答案: 使用Hibernatevalidation器进行交叉字段validation(JSR 303)

定义必须validation为true的方法,并在其顶部放置@AssertTrue注释:

  @AssertTrue private boolean isOk() { return someField != something || otherField != null; } 

该方法必须从“是”开始。

你应该使用自定义的DefaultGroupSequenceProvider<T>

ConditionalValidation.java

 // Marker interface public interface ConditionalValidation {} 

MyCustomFormSequenceProvider.java

 public class MyCustomFormSequenceProvider implements DefaultGroupSequenceProvider<MyCustomForm> { @Override public List<Class<?>> getValidationGroups(MyCustomForm myCustomForm) { List<Class<?>> sequence = new ArrayList<>(); // Apply all validation rules from ConditionalValidation group // only if someField has given value if ("some value".equals(myCustomForm.getSomeField())) { sequence.add(ConditionalValidation.class); } // Apply all validation rules from default group sequence.add(MyCustomForm.class); return sequence; } } 

MyCustomForm.java

 @GroupSequenceProvider(MyCustomFormSequenceProvider.class) public class MyCustomForm { private String someField; @NotEmpty(groups = ConditionalValidation.class) private String fieldTwo; @NotEmpty(groups = ConditionalValidation.class) private String fieldThree; @NotEmpty private String fieldAlwaysValidated; // getters, setters omitted } 

另请参阅有关此主题的相关问题 。

一种不同的方法是创build一个(受保护的)getter,它返回一个包含所有依赖字段的对象。 例:

 public class MyBean { protected String status; protected String name; @StatusAndSomethingValidator protected StatusAndSomething getStatusAndName() { return new StatusAndSomething(status,name); } } 

StatusAndSomethingValidator现在可以访问StatusAndSomething.status和StatusAndSomething.something并进行相关性检查。