我有一个特定的要求,即使它看起来非常简单。
我有一个用户表单(给你一个简化版本)。
public class Form{
@NotEmpty(message = "{empty}")
@Size(min = 3, max = 32, message = "{size}")
private String firstName;
@NotEmpty(message = "{empty}")
@Size(min = 3, max = 32, message = "{size}")
private String lastName;
}
我希望两个字段都独立验证,第一次出错时失败(只显示一条错误信息)。
例如,如果我发送firstName =“”和lastName =“aa”,我想为lastName获取firstName和size消息的空消息。
但通过这样做我得到firstName(大小和空)的2条错误消息。
我找到的第一个替代方案是使用@groupsequences但仍无法独立验证字段。
所以我创建了一个新的注释:
@Documented
@Constraint(validatedBy = {})
@Retention(RetentionPolicy.RUNTIME)
@NotEmpty(message = "{empty}", groups = Check.firstTry.class)
@Size(min = 5, max = 32, message = "{size}", groups = Check.secondTry.class)
@GroupSequence({ Check.firstTry.class, Check.secondTry.class, Name.class })
public @interface Name {
public abstract String message() default "{empty}";
public abstract Class<?>[] groups() default {};
public abstract Class<?>[] payload() default {};
}
但它仍在验证每条消息。
如果我使用@ReportAsSingleViolation,它将始终返回默认消息。
我错过了什么地方,对于这种情况,表格验证应该很容易,这不是一个奇怪的案例,是吗?
谢谢
答案 0 :(得分:1)
编写一个自定义ConstraintValidator,逐个检查约束并报告它找到的第一个约束。这个(相当大的)缺点是你最终重新实现了每个组件注释的检查机制,但是你可以完全控制错误信息。
public class MyConstraintValidator implements ConstraintValidator<Name, String> {
private Name annotation;
@Override
public void initialize(MyConstraintAnnotation annotation) {
this.annotation = annotation;
}
@Override
public boolean isValid(String name, ConstraintValidatorContext context) {
if (name == null) {
context.buildConstraintViolationWithTemplate(emptyMessage).addConstraintViolation();
return false;
} else if (name.length() < getMinSize(annotation)) {
context.buildConstraintViolationWithTemplate(tooShortMessage).addConstraintViolation();
return false;
} else if (name.length > getMaxSize(annotation)) {
context.buildConstraintViolationWithTemplate(tooLongMessage).addConstraintViolation();
return false;
} else {
return true;
}
}
}
也许你可以获得ConstraintValidatorFactory的句柄并获得每个组合注释所需的ConstraintValidators?虽然这会让您了解实现的内部。它根本不是一个完美的答案,但它会得到你所需要的。