javabean验证中的多个约束注释

javabean验证中的多个约束注释,java,bean-validation,hibernate-validator,Java,Bean Validation,Hibernate Validator,我对一个字段上有多个约束注释的情况感到困惑,如下所示: public class Student { @NotNull @Size(min = 2, max = 14, message = "The name '${validatedValue}' must be between {min} and {max} characters long") private String name; public String getName() {

我对一个字段上有多个约束注释的情况感到困惑,如下所示:

    public class Student
{
    @NotNull
    @Size(min = 2, max = 14, message = "The name '${validatedValue}' must be between {min} and {max} characters long")
    private String name;

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}
测试用例:

public class StudentTest
{
    private static Validator validator;

    @BeforeClass
    public static void setUp()
    {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();

        System.out.println(Locale.getDefault());
    }

    @Test
    public void nameTest()
    {
        Student student = new Student();
        student.setName(null);

        Set<ConstraintViolation<Student>> constraintViolations = validator.validateProperty(student, "name");

        System.out.println(constraintViolations.size());
        System.out.println(constraintViolations.iterator().next().getMessage());

    }

}
也就是说,当违反@NotNull约束时,它将不会继续。是的,这是正确的情况。当一个检查失败时,我们不希望它检查下一个约束。但是当我使用自定义约束时,情况就不同了

我定义了两个自定义约束ACheck和BCheck

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { ACheckValidator.class })
public @interface ACheck
{
    String message() default "A check error";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };
}

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { BCheckValidator.class })
public @interface BCheck
{
    String message() default "B check error";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };
}

public class ACheckValidator implements ConstraintValidator<ACheck, String>
{

    public void initialize(ACheck constraintAnnotation)
    {
    }

    public boolean isValid(String value, ConstraintValidatorContext context)
    {
        return false;
    }

}

public class BCheckValidator implements ConstraintValidator<BCheck, String>
{

    public void initialize(BCheck constraintAnnotation)
    {
    }

    public boolean isValid(String value, ConstraintValidatorContext context)
    {
        return false;
    }

}
再次测试,结果为:

1 
Can't be null
2
B check error
也就是说,当@ACheck约束被违反时,它也会检查@BCheck,为什么会发生这种情况,还有什么我忽略的吗

当违反@NotNull约束时,它将不会继续

这是不正确的。它将继续检查所有其他约束。只是大小验证器将空值视为可接受的值。原因是,通常情况下,您希望

  • 非空的最小大小值:然后应用这两个约束
  • 或可为空的值,如果该值存在,则该值必须具有最小大小:然后仅应用大小
当违反@NotNull约束时,它将不会继续

这是不正确的。它将继续检查所有其他约束。只是大小验证器将空值视为可接受的值。原因是,通常情况下,您希望

  • 非空的最小大小值:然后应用这两个约束
  • 或可为空的值,如果该值存在,则该值必须具有最小大小:然后仅应用大小

您误解了这些验证器——它们是在验证器中进行评估的

默认情况下,约束不按特定顺序求值,而不管它们属于哪个组

这意味着你的
ACheck
BCheck
可能失败,或者两者都失败了;还不能确定哪种故障将首先发生

如果希望能够使用两个不同的注释定义排序,那么必须使用
@GroupSequence
来指定该顺序

或者,如果你想快速失败,那么


我个人不鼓励这种方法,因为这意味着,验证失败的用户必须在每次出现错误时重复请求资源,而不是预先获取所有错误的内容。

您误解了这些验证器——在这些验证器中对它们进行评估

默认情况下,约束不按特定顺序求值,而不管它们属于哪个组

这意味着你的
ACheck
BCheck
可能失败,或者两者都失败了;还不能确定哪种故障将首先发生

如果希望能够使用两个不同的注释定义排序,那么必须使用
@GroupSequence
来指定该顺序

或者,如果你想快速失败,那么


我个人不鼓励这种方法,因为这意味着,验证失败的用户必须在每一件事情出错时重复请求资源,而不是预先得到所有出错的东西。

是的,我错了,我只是看到了外观@谢谢。是的,我错了,我只是看到了外表@谢谢你。
2
B check error
Validator validator = Validation.byProvider( HibernateValidator.class )
        .configure()
        .failFast( true )
        .buildValidatorFactory()
        .getValidator();