Java 如何有条件地调用spring验证器
我有一个像下面这样的模型。现有代码已经对单个属性进行了验证。现在我有一个要求,如果Java 如何有条件地调用spring验证器,java,spring,validation,Java,Spring,Validation,我有一个像下面这样的模型。现有代码已经对单个属性进行了验证。现在我有一个要求,如果买家,则忽略对账单国家和地址的现有验证。方法是foo。我想我可以有一个buyer级别的自定义验证器,只在buyer.method=foo。这是一种有效的方法吗?还有更好的选择吗 "buyer": { "method": "foo", "instruments": [ { "card": { "type": "MASTERCARD",
买家,则忽略对账单国家和地址的现有验证。方法是foo
。我想我可以有一个buyer
级别的自定义验证器,只在buyer.method=foo
。这是一种有效的方法吗?还有更好的选择吗
"buyer": {
"method": "foo",
"instruments": [
{
"card": {
"type": "MASTERCARD",
"number": "234234234234234",
"expire_month": "12",
"expire_year": "2017",
"billing_country" : "US"
"Address" : {
"line1": "summer st",
"city": "Boston"
"country": "US"
}
}
}
]
}
有两种方法可以做到这一点
你也可以
创建一个自定义验证注释和验证器,用于检查方法的值,然后将相应的验证应用于其他字段
使用,手动检查方法的值,然后选择要使用的组;然后,需要将带注释的字段更改为仅在该组处于活动状态时应用
选项#1
定义类级注释:
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { MethodAndInstrumentsValidator.class })
@Documented
public @interface ValidMethodAndInstruments {
String message() default "{my.package.MethodAndInstruments.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
选项2
在这里,您必须手动调用验证
首先,定义验证组:
public interface FooValidation {}
public interface NotFooValidation {}
配置验证器:
public class MethodAndInstrumentsValidator
implements ConstraintValidator<ValidMethodAndInstruments, Buyer> {
public final void initialize(final ValidMethodAndInstruments annotation) {
// setup
}
public final boolean isValid(final Buyer value,
final ConstraintValidatorContext context) {
// validation logic
if(!"foo".equals(value.getMethod())) {
// do whatever conditional validation you want
}
}
}
@Bean
public LocalValidatorFactoryBean validatorFactory() {
return new LocalValidatorFactoryBean();
}
在控制器(?)中,检查方法的值
,并执行验证:
@Autowired
private Validator validator;
// ...
public void validate(Object a, Class<?>... groups) {
Set<ConstraintViolation<Object>> violations = validator.validate(a, groups);
if(!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}
// ...
validate(buyer, "foo".equals(buyer.getMethod())
? FooValidation.class
: NotFooValidation.class);
@比尔巴杰的回答在某种程度上有所帮助,所以我将接受他的回答。然而,我还想记下我们在这个方法中遇到的几个问题。我们无法对地址使用@Null
和@NotNull
注释,因为它可能为Null。其次,由于我们必须将其包装在自定义约束验证器中,因此对于notfoovalization.class
,我们得到了不需要的额外验证消息字符串。最后,我们无法使用@Valid
中的组,该组已存在于地址中。我们尝试了@验证
,但由于某种原因,没有成功。我们最终实现了ReaderInterceptor
来拦截请求并手动调用所需的验证。希望这对以后的人有所帮助
@Autowired
private Validator validator;
// ...
public void validate(Object a, Class<?>... groups) {
Set<ConstraintViolation<Object>> violations = validator.validate(a, groups);
if(!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
}
// ...
validate(buyer, "foo".equals(buyer.getMethod())
? FooValidation.class
: NotFooValidation.class);
public class Buyer {
// ...
@Null(groups = FooValidation.class)
@NotNull(groups = NotFooValidation.class)
protected String billingCountry;
}