仅在表单字段上验证一个spring注释,并独立于其他字段

时间:2013-05-24 08:22:23

标签: java forms spring annotations validation

我有一个特定的要求,即使它看起来非常简单。

我有一个用户表单(给你一个简化版本)。

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,它将始终返回默认消息。

我错过了什么地方,对于这种情况,表格验证应该很容易,这不是一个奇怪的案例,是吗?

谢谢

1 个答案:

答案 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?虽然这会让您了解实现的内部。它根本不是一个完美的答案,但它会得到你所需要的。