依赖于其他字段的Spring自定义验证器



我们正在为控制器端点中使用的请求对象使用spring自定义验证器。我们的实现方式与下面的链接相同:

https://www.baeldung.com/spring-mvc-custom-validator

我们面临的问题是,如果特定字段也依赖于其他输入字段,它就无法工作。例如,我们将下面的代码作为控制器端点的请求对象:

public class FundTransferRequest {
private String accountTo;
private String accountFrom;
private String amount;

@CustomValidator
private String reason;
private Metadata metadata;
}
public class Metadata {
private String channel; //e.g. mobile, web, etc.
}

基本上@CustomValidator是我们的自定义验证器类,我们想要的逻辑是,如果从元数据提供的通道是"WEB"该领域"原因";的请求是不需要的。否则,它将被要求。

有办法做到这一点吗?我做了额外的研究,没有看到任何处理这种情况的。

显然,如果您需要访问自定义验证器中的多个字段,则必须使用类级注释。

你提到的同一篇文章有一个例子:https://www.baeldung.com/spring-mvc-custom-validator#custom-class-level-validation

在你的例子中,它可能看起来像这样:

@Constraint(validatedBy = CustomValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomValidation {
String message() default "Reason required";
String checkedField() default "metadata.channel";
String checkedValue() default "WEB";
String requiredField() default "reason";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
package com.example.demo;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.stereotype.Component;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/*
If the supplied channel from Metadata is "WEB". The field "reason" of the request won't be required.
Else, it will be required.
*/
@Component
public class CustomValidator implements ConstraintValidator<CustomValidation, Object> {
private String checkedField;
private String checkedValue;
private String requiredField;
@Override
public void initialize(CustomValidation constraintAnnotation) {
this.checkedField = constraintAnnotation.checkedField();
this.checkedValue = constraintAnnotation.checkedValue();
this.requiredField = constraintAnnotation.requiredField();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
Object checkedFieldValue = new BeanWrapperImpl(value)
.getPropertyValue(checkedField);
Object requiredFieldValue = new BeanWrapperImpl(value)
.getPropertyValue(requiredField);
return checkedFieldValue != null && checkedFieldValue.equals(checkedValue) || requiredFieldValue != null;
}
}

的用法是:

@CustomValidation
public class FundTransferRequest {
...

或带有指定参数的

@CustomValidation(checkedField = "metadata.channel", 
checkedValue = "WEB", 
requiredField = "reason", 
message = "Reason required")
public class FundTransferRequest {
...

最新更新