【问题标题】:Building Dynamic ConstraintViolation Error Messages构建 Dynamic ConstraintViolation 错误消息
【发布时间】:2023-04-03 16:08:01
【问题描述】:

我编写了一个由自定义ConstraintValidator 实现的验证注释。我还想生成非常具体的 ConstraintViolation 对象,这些对象使用在消息插值期间的验证过程中计算的值。

public class CustomValidator 
  implements ConstraintValidator<CustomAnnotation, ValidatedType> {

...
  @Override
  public boolean isValid(ValidatedType value, ConstraintValidatorContext context) {
    // Figure out that the value is not valid.
    // Now, I want to add a violation whose error message requires arguments.
  }
}

我的消息源中的假设错误消息:

CustomAnnotation.notValid = The supplied value {value} was not valid because {reason}.

传递给isValid 方法的上下文提供了一个接口,用于构建约束冲突,并最终将其添加到上下文中。但是,我似乎无法弄清楚如何使用它。根据我正在使用的版本的documention,我可以将 bean 和属性节点添加到违规中。这些是我可以为违规定义指定的唯一其他详细信息,但我不明白它们如何映射到错误消息中的参数。

百万美元问题:如何使用自定义验证器将动态参数传递给我的验证错误消息?我想使用 ConstraintValidatorContext 填写 {value}{reason} 字段的建筑违规界面。

获取消息源的实例并在自定义验证器中插入消息不是一种选择 - 来自验证的消息无论如何都会被插入,并且内部插入将导致某些消息被插入两次,可能会消灭转义我的消息定义文件中的单引号或其他具有特殊含义的字符。

【问题讨论】:

    标签: hibernate validation bean-validation


    【解决方案1】:

    这对于标准化的 Bean Valiation API 是不可能的,但是在 Hibernate Validator 中,BV 参考实现有一种方法。

    您需要将ConstraintValidatorContext 解包为HibernateConstraintValidatorContext,这样您就可以访问addExpressionVariable() 方法:

    public class MyFutureValidator implements ConstraintValidator<Future, Date> {
    
        public void initialize(Future constraintAnnotation) {}
    
        public boolean isValid(Date value, ConstraintValidatorContext context) {
            Date now = GregorianCalendar.getInstance().getTime();
    
            if ( value.before( now ) ) {
                HibernateConstraintValidatorContext hibernateContext =
                    context.unwrap( HibernateConstraintValidatorContext.class );
    
                hibernateContext.disableDefaultConstraintViolation();
                hibernateContext.addExpressionVariable( "now", now )
                    .buildConstraintViolationWithTemplate( "Must be after ${now}" )
                    .addConstraintViolation();
    
                return false;
            }
    
            return true;
        }
    }
    

    参考指南有一些more details

    【讨论】:

    • 为了记录,我接受了这个答案,因为你说这是不可能的。文档中的示例实际上对我不起作用,因为我的约束违规模板本身就是消息代码,并且我无法访问最终消息中的自定义“表达式变量”。 (错误信息总是无法解析代码。)
    【解决方案2】:

    如果您使用消息代码,您可以简单地在其中添加 {0} 之类的内容。

    例如:“字段 {0} 不得为空。”

    然后使用hibernateContext.addMessageParameter("0", fieldName); 而不是addExpressionVariable(...)

    这对我有用。

    【讨论】:

    • 此外,如果您使用消息代码并希望传递正在验证的字段的值 - 您可以通过 ${validatedValue} 访问它 - 例如hibernateContext. addExpressionVariable("0", fieldName)"The field {0} must not be empty. Its value is ${validatedValue}"
    猜你喜欢
    • 1970-01-01
    • 2014-04-30
    • 2023-04-07
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多