自定义Bean验证器 - JSR303 / JSR349可以验证器无效时选择消息吗?

时间:2013-07-20 15:37:14

标签: bean-validation

有没有办法让验证程序在验证失败时指定邮件?我知道我可以实现注释,所以我可以像这样使用它(在实践中可能会使用枚举而不是value的字符串):

@Check(value="Type1", message="{type1.checkFailed}") public MyClass myVal1;
@Check(value="Type2", message="{type2.checkFailed}") public MyClass myVal2;

这将得到我想要的最终结果。我还可以实现多个注释/验证器并以这种方式执行,并在注释的定义中指定默认消息:

@CheckType1 public MyClass myVal1; // default message is type1.checkFailed
@CheckType2 public MyClass myVal2; // default message is type2.checkFailed

我想做的是让与@Check相关联的验证器确定是否使用type1.checkFailedtype2.checkFailed作为消息,具体取决于value,如下所示:

@Check("Type1") public MyClass myVal1;
@Check("Type2") public MyClass myVal2;

据我了解,最佳做法是让验证员专注于一个特征。但我不认为我想要做的是与此相反,因为它是对单一特征的验证,只有它的变体可以被验证。

作为使用犬种的例子:

@BreedSize("Large") Dog bigDog;
@BreedSize("Small") Dog smallDog;

由于给定的注释只能在元素上出现一次(至少从SE7开始),这也可能是确保只进行多次互斥验证之一的合理方法。我认为有一个关于元素上同一类型的多个注释的提议,但我认为验证器可以检查只提供了一个,在这种情况下 - 尽管在这里先行了。

这可能吗?

1 个答案:

答案 0 :(得分:0)

您可以通过传递给ConstraintValidatorContext方法的isValid()创建自定义约束违规对象,如下所示:

public class BreedSizeValidator implements ConstraintValidator<BreedSize, Dog> {

    private String value;

    @Override
    public void initialize(BreedSize constraintAnnotation) {
        this.value = constraintAnnotation.value();
    }

    @Override
    public boolean isValid(
        Dog object,
        ConstraintValidatorContext constraintContext) {

        if ( object == null ) {
            return true;
        }

        boolean isValid = ...;

        if ( !isValid ) {
            String messageKey = "Large".equals( value ) ? 
                "{BreedSize.Large.message}" : "{BreedSize.Small.message}";

            constraintContext.disableDefaultConstraintViolation();
            constraintContext
                .buildConstraintViolationWithTemplate( messageKey )
                .addConstraintViolation();
        }

        return isValid;
    }
}