我很高兴宣布 Hibernate Validator 5.1 的第一个 alpha 版本发布。这个版本基于 Bean Validation 1.1 API 带来了一些新特性,以及显著的性能改进和一些错误修复。

通常,您可以从 SourceForge 下载这个版本的 发行版(ZIP 或 TAR.GZ),或者使用您偏好的依赖管理工具,在 GAV 坐标 org.hibernate:hibernate-validator:5.1.0.Alpha1 下检索。二进制文件已推送到 JBoss Maven 仓库,并应很快同步到 Maven Central。

里面有什么内容?

本版本新增的特性主要围绕 Bean Validation 1.1 提供的新 API 和功能,如方法验证和基于表达式的消息插值。让我们更详细地了解一下其中的一些。

通过 HV-714 我们添加了一个新的约束, @ParameterScriptAssert它允许使用脚本表达式验证方法或构造函数的参数

@ParametersScriptAssert(script = "arg0.before(arg1)", lang = "javascript")
public void createCalendarEvent(Date start, Date end, String title) { ... }

类似于@ScriptAssert(它适用于类级别),此约束可用于任何具有 JSR 223 兼容引擎的脚本语言。您可以选择多种选项,如 JavaScript(Java 开发工具包自带引擎)、Groovy、JRuby 等。

如示例所示,默认情况下,名称 arg0arg1 等。用于引用验证的方法或构造函数的参数。这听起来不是很清楚,但不幸的是,Java 没有提供一种标准化的方式在运行时获取参数名称(这将随着 Java 8 的到来而改变,届时可以通过反射访问参数名称)。

为了解决这个问题,Bean Validation 定义了一个 SPI(服务提供程序接口),允许插入自定义参数名称提供程序。Hibernate Validator 现在提供该 SPI 的实现(HV-802),它基于 ParaNamer 项目。ParaNamer 是一个提供多种获取运行时参数名称方式的优秀小库。

  • 它基于 Java 编译器创建的调试符号,
  • 在编译后的步骤中将参数名称编织到字节码中的常量,或
  • 如 JSR 330 中的 @Named 注解之类的注解。

要使用此参数名称提供程序,请在类路径中添加 ParaNamer 库,并在启动验证器时配置提供程序如下

Validator validator = Validation.byDefaultProvider()
    .configure()
    .parameterNameProvider( new ParanamerParameterNameProvider() )
    .buildValidatorFactory()
    .getValidator();

配置参数名称提供程序后,您可以在约束(这些名称也将用于无效参数约束的约束违反)内部引用参数的实际名称@ParameterScriptAssert

@ParametersScriptAssert(script = "start.before(end)", lang = "javascript")
public void createCalendarEvent(Date start, Date end, String title) { ... }

有关 ParaNamer 提供访问参数名称不同方式的更多信息,请参阅 ParaNamer 文档。

消息插值

另一个新的优秀特性是对ConstraintValidatorContextAPI 的扩展,它允许将任意对象添加到约束违反消息中(HV-701)。例如,让我们考虑这个用于 @Future 约束的自定义验证器@Future约束

public class MyFutureValidator implements ConstraintValidator<Future, Date> {

    public void initialize(Future constraintAnnotation) {}

    public boolean isValid(Date value, ConstraintValidatorContext context) {
        if ( value == null ) { return true; }

        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 ${formatter.format( '%1$te.%1$tm.%1$tY %1$tH:%1$tM', now ) }"
                )
                .addConstraintViolation();

            return false;
        }

        return true;
    }
}

而不是仅使用“必须在将来”作为约束违反消息,此验证器将当前时间添加到消息中。为此,在验证上下文中添加了一个名为“now”的表达式变量,它包含一个Date对象,表示当前时间。使用变量名称,可以从违反消息内部访问它,并按示例格式化。

性能改进

除了添加新功能外,我们还努力确保 Hibernate Validator 提供您应得的性能。在整个广泛的配置文件会话中,我们确定了几个性能瓶颈,例如围绕消息插值的瓶颈(HV-637)。性能调整(在内存消耗以及执行速度方面)是一个持续的工作,您可以在下一个版本中期待该领域的进一步改进。

这标志着我们对 Hibernate Validator 5.1.0.Alpha1 的新功能的介绍结束。您可以在 发布说明 中找到所有已解决的问题的完整列表。《参考指南》详细描述了所有新增功能。

请通过添加评论或发布到 论坛 来告诉我们您对此次新版本的看法。如果您发现了一个错误,请务必为它提交一个 JIRA 问题。或者,更好的是,分叉 代码库 并提交一个包含所需修复的拉取请求。要讨论任何开发相关的问题,只需向 hibernate-dev 列表发送消息。


返回顶部