0

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

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

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",我想获得 firstName 的空消息和 lastName 的 size 消息。

但是通过这样做,我收到了 2 条关于 firstName 的错误消息(大小和空)。

我发现的第一个替代方法是使用 @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,它将始终返回默认消息。

我是否在某个地方遗漏了什么,对于这种情况,表单验证应该很容易,这不是一个奇怪的情况,是吗?

谢谢你

4

1 回答 1

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

于 2013-05-24T09:31:01.430 回答