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

Java 仅验证表单字段上的一个spring注释,并独立于其他字段,java,forms,spring,annotations,validation,Java,Forms,Spring,Annotations,Validation,我有一个具体的要求,即使它看起来很简单 我有一个用户表单(给你一个简化版本) 我希望这两个字段都是独立验证的,在第一个错误时失败(然后只显示一条错误消息) 例如,如果我发送firstName=“”和lastName=“aa”,我希望得到firstName的空消息和lastName的size消息 但是通过这样做,我得到了firstName的两条错误消息(size和empty) 我发现的第一个替代方法是使用@groupsequences,但仍然无法独立验证字段 因此,我创建了一个新注释: @Docu

我有一个具体的要求,即使它看起来很简单

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

我希望这两个字段都是独立验证的,在第一个错误时失败(然后只显示一条错误消息)

例如,如果我发送firstName=“”和lastName=“aa”,我希望得到firstName的空消息和lastName的size消息

但是通过这样做,我得到了firstName的两条错误消息(size和empty)

我发现的第一个替代方法是使用@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 {};
}
@已记录
@约束(validatedBy={})
@保留(RetentionPolicy.RUNTIME)
@NotEmpty(message=“{empty}”,groups=Check.firstTry.class)
@大小(最小值=5,最大值=32,message=“{Size}”,groups=Check.secondTry.class)
@GroupSequence({Check.firstTry.class,Check.secondTry.class,Name.class})
public@interface Name{
公共抽象字符串消息()默认值“{empty}”;
公共抽象类[]组()默认值{};
公共抽象类[]有效负载()默认值{};
}
但它仍然在验证每一条消息

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;
        }
    }
}
如果我使用@ReportAssingeViolation,它将始终返回默认消息

我是不是遗漏了什么,表单验证对于这个案例应该很容易,这不是一个奇怪的案例,是吗


谢谢

编写一个自定义约束验证程序,逐个检查约束并报告找到的第一个约束。这样做(相当大)的缺点是,您最终会重新实现每个组件注释的检查机制,但您确实可以完全控制错误消息

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;
        }
    }
}
公共类MyConstraintValidator实现ConstraintValidator{
私名注释;
@凌驾
公共void初始化(myConstraintAnotation注释){
this.annotation=注释;
}
@凌驾
公共布尔值有效(字符串名称、ConstraintValidatorContext上下文){
if(name==null){
buildConstraintViolationWithTemplate(emptyMessage).addConstraintViolation();
返回false;
}else if(name.length()getMaxSize(注释)){
buildConstraintViolationWithTemplate(tooLongMessage).addConstraintViolation();
返回false;
}否则{
返回true;
}
}
}

如果您可以获得ConstraintValidatorFactory的句柄,并获得每个合成注释所需的ConstraintValidator,也许可以?尽管这会让您了解实现的内部结构。这根本不是一个完美的答案,但它会得到你需要的。

但它总是会返回相同的错误消息。我希望每个约束都有不同的消息。这是你的权利,谢谢。但这意味着我没有错,他们的方法不是标准的吗?我是唯一一个认为它应该是基本配置的人吗?首先,我不知道java是否保证注释以任何“顺序”存在,它们要么存在,要么不存在。如果是这样,那么“first”约束的概念就没有多大意义。事实上,查看Class.java的源代码,注释保存在HashMap中,因此没有顺序。当然,这完全取决于实现。我仍然需要在注释声明中添加一条始终出现的消息。我可以将其设置为空字符串,但这意味着我总是有两个错误条目,一个是真实的,另一个是空字符串…有解决方案吗?