Hyp*_*ate 4 java validation spring annotations spring-mvc
这里有一个小贪婪的问题,希望这个也可以帮助那些想要了解更多关于注释验证的人
我目前正在学习Spring,现在,我计划尝试自定义注释验证.
我已经搜索了很多,现在我知道主要有两种验证,一种用于控制器,另一种是使用@Valid的注释方法
所以这是我的场景:假设我有两个或更多字段,当它们是ALL NULL时可以为null.但只有当其中一个字段包含除空字符串之外的任何值时,这些字段才需要输入.我有两个想法,但不知道如何正确实现它们.
这是类示例:
public class Subscriber {
private String name;
private String email;
private Integer age;
private String phone;
private Gender gender;
private Date birthday;
private Date confirmBirthday;
private String birthdayMessage;
private Boolean receiveNewsletter;
//Getter and Setter
}
Run Code Online (Sandbox Code Playgroud)
假设我想生日和confirmBirthday字段需要为空或反对,我可能想要为每个使用一个注释注释它们,看起来像这样:
public class Subscriber {
private String name;
private String email;
private Integer age;
private String phone;
private Gender gender;
@NotNullIf(fieldName="confirmBirthday")
private Date birthday;
@NotNullIf(fieldName="birthday")
private Date confirmBirthday;
private String birthdayMessage;
private Boolean receiveNewsletter;
//Getter and Setter
}
Run Code Online (Sandbox Code Playgroud)
所以我需要像这样创建验证Annotation:
@Documented
@Constraint(validatedBy = NotNullIfConstraintValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD })
public @interface NotNullIf {
String fieldName();
String message() default "{NotNullIf.message}";
Class<?>[] group() default {};
Class<? extends Payload>[] payload() default {};
}
Run Code Online (Sandbox Code Playgroud)
之后我将需要创建Validator本身:
public class NotNullIfConstraintValidator implements ConstraintValidator<NotNullIf, String>{
private String fieldName;
public void initialize(NotNullIf constraintAnnotation) {
fieldName = constraintAnnotation.fieldName();
}
public boolean isValid(String value, ConstraintValidatorContext context) {
if(value == null) {
return true;
};
//TODO Validation
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
对于另一个想法使用相同的类作为一个例子说我想要生日,confirmBirthday和birthdayMessdage只能是null或同时反对.我这次可能需要使用类注释验证来进行跨领域验证.
这是我想如何注释类:
@NotNullIf(fieldName={"birthday", "confirmBirthday", "birthdayMessage"})
public class Subscriber {
//Those field same as the above one
}
Run Code Online (Sandbox Code Playgroud)
因此,当其中一个字段不为null时,还需要在客户端大小上输入其余字段.可能吗?
我读过这篇文章:如何访问注释属性中描述的字段
但我仍然对注释验证如何从我上面列出的那些元素起作用感到困惑.也许我需要对该代码进行一些细节解释,或者更糟糕的是我可能需要一些基本的概念检查.
请帮忙!
为此,您只能使用类型级别注释,因为字段级别注释无法访问其他字段!
我做了类似的事情以允许选择验证(确切地说,许多属性中的一个必须不为null).在您的情况下,@AllOrNone注释(或您喜欢的任何名称)将需要一个字段名称数组,您将获得带注释类型的整个对象到验证器:
@Target(ElementType.TYPE)
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = AllOrNoneValidator.class)
public @interface AllOrNone {
String[] value();
String message() default "{AllOrNone.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class AllOrNoneValidator implements ConstraintValidator<AllOrNone, Object> {
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
private String[] fields;
@Override
public void initialize(AllOrNone constraintAnnotation) {
fields = constraintAnnotation.value();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
long notNull = Stream.of(fields)
.map(field -> PARSER.parseExpression(field).getValue(value))
.filter(Objects::nonNull)
.count();
return notNull == 0 || notNull == fields.length;
}
}
Run Code Online (Sandbox Code Playgroud)
(正如你所说的使用Spring我使用SpEL来允许甚至嵌套字段访问)
现在您可以注释您的Subscriber类型:
@AllOrNone({"birthday", "confirmBirthday"})
public class Subscriber {
private String name;
private String email;
private Integer age;
private String phone;
private Gender gender;
private Date birthday;
private Date confirmBirthday;
private String birthdayMessage;
private Boolean receiveNewsletter;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8937 次 |
| 最近记录: |