如何获取ConstraintValidatorContext?

我正在编写显式调用Bean Validation(JSR-303)的代码,如下所示:

public class Example { @DecimalMin(value = "0") private static final String ANNOTATED = ""; public void isPossitiveNumber(String str){ ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ConstraintValidator validator = factory.getConstraintValidatorFactory().getInstance( DecimalMinValidatorForString.class); validator.initialize( ReflectionUtils.findField(getClass(), "ANNOTATED") .getAnnotation( DecimalMin.class)); boolean isValid = validator.isValid(str, null); return isValid; } } 

注意行boolean isValid = validator.isValid(str,null); 我为ConstraintValidatorContext传递null ,因为我找不到获取/构造它的方法。 在这种特殊情况下,这个很好,因为内部没有使用ConstraintValidatorContext ,但很明显是一个hack。 我该如何获得ConstraintValidatorContext

添加

我被要求提供用例。 因此,例如,我正在编写自定义validation器,我想重用现有的validation。 或者我正在编写上面描述的平面Java代码,我想重用现有的validation。

简单的答案是你不能。 ConstraintValidatorContext是一个接口,没有Bean Validation API来获取这样的实例。 您可以编写自己的实现,但要正确实现它,您必须重新实现Bean Validation提供程序的许多function。 查看Hibernate Validator特定实现的示例 – https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl。 java的

也就是说,我相信你的重用尝试是错误的。 这不是Beanvalidation的缩进,您最终会得到不可移植且难以维护的代码。 如果要重用现有约束,请查看约束组合,例如@NotEmpty重用@NotNull和@Size

 @Documented @Constraint(validatedBy = { }) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @ReportAsSingleViolation @NotNull @Size(min = 1) public @interface NotEmpty { String message() default "{org.hibernate.validator.constraints.NotEmpty.message}"; Class[] groups() default { }; Class[] payload() default { }; /** * Defines several {@code @NotEmpty} annotations on the same element. */ @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Documented public @interface List { NotEmpty[] value(); } } 

在这种情况下,您应该为您validation的约束声明一个组。 然后,您可以调用该组的正常validation。 有关组定义及其语义,请参阅规范的第2.1.1.2节和第3.4节。 要validation组,您只需要调用Validator.validate(T Object, Class... groups) 。 在这种情况下,不需要使用ConstraintValidatorContext

我最近和OP有完全相同的问题。 但是,与接受的答案相反,可以编写包含ConstraintValidationContext的unit testing。 这个优秀的链接解释了如何做到这一点, http://farenda.com/java/bean-validation-unit-testing/

基本上,您需要使用ValidatorFactory来获取Validator接口,然后在该接口上调用validate(c),其中参数c是包含beanvalidation注释的类的实例。 代码示例更清晰,代码示例取自上面的链接。

  public class Player { // name have to be 3 chars: @Size(min = 3, max = 3) private String name; // possible score in game: @Min(0) @Max(100) private int score; public Player(String name, int score) { this.name = name; this.score = score; } // just for logs @Override public String toString() { return "Player{name='" + name + '\'' + ", score=" + score + '}'; } } public class PlayerValidationTest { private static ValidatorFactory validatorFactory; private static Validator validator; @BeforeClass public static void createValidator() { validatorFactory = Validation.buildDefaultValidatorFactory(); validator = validatorFactory.getValidator(); } @AfterClass public static void close() { validatorFactory.close(); } @Test public void shouldDetectInvalidName() { //given too short name: Player player = new Player("a", 44); //when: Set> violations = validator.validate(player); //then: assertEquals(violations.size(), 1); } 

}