上篇完美实现校验:利用Spring Validation实现强大的输入验证我们通过Spring Validation实现参数的校验,今天我们看下多字段联合校验。
当根据一个字段的值来决定另一个字段的校验时,我们可以使用ConstraintValidator来实现自定义的校验逻辑。
在下面的示例中,我们假设根据登录类型来决定手机号码的校验逻辑。
首先,我们定义一个自定义的校验注解 PhoneValidation:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
@Documented
public @interface PhoneValidation {
String message() default "Invalid phone number";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String loginTypeField();
String phoneField();
}
接着,我们实现对应的验证器 PhoneValidator:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
public class PhoneValidator implements ConstraintValidator<PhoneValidation, Object> {
private String loginTypeField;
private String phoneField;
@Override
public void initialize(PhoneValidation constraintAnnotation) {
loginTypeField = constraintAnnotation.loginTypeField();
phoneField = constraintAnnotation.phoneField();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
try {
Field userType = value.getClass().getDeclaredField(loginTypeField);
userType.setAccessible(true);
String userTypeValue = (String) userType.get(value);
Field phoneNumber = value.getClass().getDeclaredField(phoneField);
phoneNumber.setAccessible(true);
String phoneNumberValue = (String) phoneNumber.get(value);
if ("1".equals(userTypeValue)) {
return phoneNumberValue != null && !phoneNumberValue.isEmpty();
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
在这个示例中,我们设置登录类型为 "1" 时,手机号码不能为空。isValid 方法中使用了反射来获取字段值并进行校验。
最后,我们可以在实体类上应用自定义的校验注解:
import lombok.Data;
@Data
@PhoneValidation(loginTypeField = "loginType", phoneField = "phoneNumber")
public class User {
private String loginType;
private String phoneNumber;
}
现在,当你使用 Bean Validation 来验证 User 对象时,会根据用户类型来决定手机号码的校验逻辑:
public class Main {
public static void main(String[] args) {
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
User user = new User();
user.setLoginType("1");
user.setPhoneNumber(null);
Set<ConstraintViolation<User>> violations = validator.validate(user);
for (ConstraintViolation<User> violation : violations) {
System.out.println(violation.getMessage());
}
}
}
当我们传入空手机号时输出错误信息
Invalid phone number