我正在编写显式调用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<DecimalMin, String>
validator =
factory.getConstraintValidatorFactory().getInstance(
DecimalMinValidatorForString.class);
validator.initialize(
ReflectionUtils.findField(getClass(), "ANNOTATED")
.getAnnotation(
DecimalMin.class));
boolean isValid = validator.isValid(str, null);
return isValid;
}
}
注意布尔值isValid = validator.isValid(str,null);
我为null
转移ConstraintValidatorContext
因为我找不到获取/构建它的方法。在这种特殊情况下,这很好,因为内部没有使用ConstraintValidatorContext
,但很明显是黑客攻击。我应该如何获得ConstraintValidatorContext
?
ADDED
我被要求提供用例。因此,例如,我正在编写自定义验证器,我想重用现有的验证。或者我正在编写如上所述的平面Java代码,我想重用现有的验证。
答案 0 :(得分:1)
简单的答案是你不能。 ConstraintValidatorContext 是一个接口,没有Bean Validation API来获取这样的实例。您可以编写自己的实现,但要正确实现它,您必须重新实现Bean Validation提供程序的许多功能。查看Hibernate Validator特定实现的示例 - https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java
那就是说,我相信你的重用尝试是错误的。这不是Bean Validation的缩进,你最终会得到不可移植且难以维护的代码。如果要重用现有约束,请查看约束组合,例如@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<? extends Payload>[] 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();
}
}
答案 1 :(得分:0)
在这种情况下,您应该为您验证的约束声明一个组。然后,您可以调用该组的正常验证。有关组定义及其语义,请参阅规范的第2.1.1.2节和第3.4节。要验证该组,您只需拨打Validator.validate(T Object, Class<?>... groups)
即可。在这种情况下,没有必要使用ConstraintValidatorContext
。
答案 2 :(得分:0)
我最近和OP有完全相同的问题。但是,与接受的答案相反,可以编写包含ConstraintValidationContext的单元测试。这个优秀的链接解释了如何执行此操作,http://farenda.com/java/bean-validation-unit-testing/
基本上,您需要使用ValidatorFactory来获取Validator接口,然后在该接口上调用validate(c),其中参数c是包含bean验证注释的类的实例。代码示例更清晰,代码示例取自上面的链接。
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<ConstraintViolation<Player>> violations
= validator.validate(player);
//then:
assertEquals(violations.size(), 1);
}
}