Spring 基于自定义条件的验证
Spring custom condition based validation
我想在 spring 验证器中创建基于条件的验证。
我有一个 UserDTO class 因为有两个 DTO class 带有 @Valid
注释。
如果我传递 isPrimary true
那么它应该只验证 primaryDTO bean 并忽略 secendoryDTO 验证。
public class UserDTO {
@Valid
private PrimaryDTO primaryDTO;
@Valid
private SecendoryDTO secendoryDTO;
private boolean isPrimary;
}
public class PrimaryDTO {
@NotEmpty(message = "Please enter email.")
@Email(message = "Please enter a valid email.")
private String email;
}
public class SecendoryDTO {
@NotEmpty(message = "Please enter phone.")
private String phone;
}
请指导。
谢谢
如果您的验证依赖于多个字段(例如 isPrimary
和 primaryDTO
或 secondaryDTO
),那么唯一的解决方案是在类级别编写自定义验证程序(UserDTO
) 它将自己实现条件验证。
例如创建注解:
@Documented
@Retention(RUNTIME)
@Target({ANNOTATION_TYPE, TYPE})
@Constraint(validatedBy = SecondaryValidator.class)
public @interface ValidSecondary {
String message() default "Invalid secondary";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
并创建一个验证器,仅在 isPrimary()
为 false
时验证 secondaryDTO
字段:
@Component
public class SecondaryValidator implements ConstraintValidator<ValidSecondary, UserDTO> {
private Validator validator;
public SecondaryValidator(Validator validator) {
this.validator = validator;
}
@Override
public boolean isValid(UserDTO userDTO, ConstraintValidatorContext constraintValidatorContext) {
if (userDTO.isPrimary()) {
return true;
} else {
return validator.validate(userDTO.getSecondaryDTO()).isEmpty();
}
}
}
之后,您可以从 secondaryDTO
字段中删除 @Valid
注释,并在 UserDTO
:
顶部添加 @ValidSecondary
注释
@ValidSecondary // Add this
public class UserDTO {
@Valid
private PrimaryDTO primaryDTO;
private SecondaryDTO secondaryDTO; // No more @Valid
private boolean primary;
}
但是,在这种情况下,您将丢失来自 SecondaryDTO
中的任何约束违规消息,如果您想要某种传递机制,您可以将违规添加到 constraintValidatorContext
在 isValid()
方法中,例如:
Set<ConstraintViolation<SecondaryDTO>> violations = validator.validate(userDTO.getSecondaryDTO());
violations.forEach(violation -> constraintValidatorContext
.buildConstraintViolationWithTemplate(violation.getMessage())
.addConstraintViolation());
我想在 spring 验证器中创建基于条件的验证。
我有一个 UserDTO class 因为有两个 DTO class 带有 @Valid
注释。
如果我传递 isPrimary true
那么它应该只验证 primaryDTO bean 并忽略 secendoryDTO 验证。
public class UserDTO {
@Valid
private PrimaryDTO primaryDTO;
@Valid
private SecendoryDTO secendoryDTO;
private boolean isPrimary;
}
public class PrimaryDTO {
@NotEmpty(message = "Please enter email.")
@Email(message = "Please enter a valid email.")
private String email;
}
public class SecendoryDTO {
@NotEmpty(message = "Please enter phone.")
private String phone;
}
请指导。
谢谢
如果您的验证依赖于多个字段(例如 isPrimary
和 primaryDTO
或 secondaryDTO
),那么唯一的解决方案是在类级别编写自定义验证程序(UserDTO
) 它将自己实现条件验证。
例如创建注解:
@Documented
@Retention(RUNTIME)
@Target({ANNOTATION_TYPE, TYPE})
@Constraint(validatedBy = SecondaryValidator.class)
public @interface ValidSecondary {
String message() default "Invalid secondary";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
并创建一个验证器,仅在 isPrimary()
为 false
时验证 secondaryDTO
字段:
@Component
public class SecondaryValidator implements ConstraintValidator<ValidSecondary, UserDTO> {
private Validator validator;
public SecondaryValidator(Validator validator) {
this.validator = validator;
}
@Override
public boolean isValid(UserDTO userDTO, ConstraintValidatorContext constraintValidatorContext) {
if (userDTO.isPrimary()) {
return true;
} else {
return validator.validate(userDTO.getSecondaryDTO()).isEmpty();
}
}
}
之后,您可以从 secondaryDTO
字段中删除 @Valid
注释,并在 UserDTO
:
@ValidSecondary
注释
@ValidSecondary // Add this
public class UserDTO {
@Valid
private PrimaryDTO primaryDTO;
private SecondaryDTO secondaryDTO; // No more @Valid
private boolean primary;
}
但是,在这种情况下,您将丢失来自 SecondaryDTO
中的任何约束违规消息,如果您想要某种传递机制,您可以将违规添加到 constraintValidatorContext
在 isValid()
方法中,例如:
Set<ConstraintViolation<SecondaryDTO>> violations = validator.validate(userDTO.getSecondaryDTO());
violations.forEach(violation -> constraintValidatorContext
.buildConstraintViolationWithTemplate(violation.getMessage())
.addConstraintViolation());