Hibernate Validator 中文操作指南

1. Getting started

本章将教您如何开始使用 Jakarta Bean 验证的参考实现 (RI) Hibernate 验证器。对于以下快速入门,您需要:

This chapter will show you how to get started with Hibernate Validator, the reference implementation (RI) of Jakarta Bean Validation. For the following quick-start you need:

  1. A JDK 8

  2. Apache Maven

  3. An Internet connection (Maven has to download all required libraries)

1.1. Project set up

要在 Maven 项目中使用 Hibernate 验证器,只需将以下依赖项添加到 pom.xml

In order to use Hibernate Validator within a Maven project, simply add the following dependency to your pom.xml:

示例 1.1:Hibernate Validator Maven 依赖项

. Example 1.1: Hibernate Validator Maven dependency

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.1.Final</version>
</dependency>

这将瞬态提取到 Jakarta Bean 验证 API(jakarta.validation:jakarta.validation-api:3.0.2)的依赖项。

This transitively pulls in the dependency to the Jakarta Bean Validation API (jakarta.validation:jakarta.validation-api:3.0.2).

1.1.1. Unified EL

Hibernate Validator 需要一个@“7”的实现来评估约束违反消息中的动态表达式(请参阅@“9”)。当应用程序在 Jakarta EE 容器(例如 WildFly/JBoss EAP)中运行时,容器中已提供了 EL 实现。然而,在 Java SE 环境中,必须在 POM 文件中将实现作为依赖项添加。例如,可以添加以下依赖项以使用 Jakarta EL @“8”:

Hibernate Validator requires an implementation of Jakarta Expression Language for evaluating dynamic expressions in constraint violation messages (see Section 4.1, “Default message interpolation”). When your application runs in a Jakarta EE container such as WildFly/JBoss EAP, an EL implementation is already provided by the container. In a Java SE environment, however, you have to add an implementation as dependency to your POM file. For instance you can add the following dependency to use the Jakarta EL reference implementation:

示例 1.2:Unified EL 参考实现的 Maven 依赖项

. Example 1.2: Maven dependencies for Unified EL reference implementation

<dependency>
    <groupId>org.glassfish.expressly</groupId>
    <artifactId>expressly</artifactId>
    <version>5.0.0</version>
</dependency>

对于无法提供 EL 实现的环境,Hibernate Validator 提供一个 Section 12.10, “ParameterMessageInterpolator 。但是,使用此内插器不符合 Jakarta Bean Validation 规范。

For environments where one cannot provide a EL implementation Hibernate Validator is offering a Section 12.10, “ParameterMessageInterpolator. However, the use of this interpolator is not Jakarta Bean Validation specification compliant.

1.1.2. CDI

Jakarta Bean Validation 定义了与 CDI 的集成点 ( Contexts and Dependency Injection for Jakarta EE)。如果你的应用程序在默认情况下不提供此集成的环境中运行,你可以使用 Hibernate Validator CDI 便携扩展,方法是向你的 POM 添加以下 Maven 依赖关系:

Jakarta Bean Validation defines integration points with CDI (Contexts and Dependency Injection for Jakarta EE). If your application runs in an environment which does not provide this integration out of the box, you may use the Hibernate Validator CDI portable extension by adding the following Maven dependency to your POM:

示例 1.3:Hibernate Validator CDI 可移植扩展 Maven 依赖项

. Example 1.3: Hibernate Validator CDI portable extension Maven dependency

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-cdi</artifactId>
    <version>8.0.1.Final</version>
</dependency>

请注意,对于在 Jakarta EE 应用服务器上运行的应用程序,通常不需要添加此依赖项。可以在“10”中了解更多关于 Jakarta Bean Validation 和 CDI 的集成情况。

Note that adding this dependency is usually not required for applications running on a Jakarta EE application server. You can learn more about the integration of Jakarta Bean Validation and CDI in Section 11.3, “CDI”.

1.1.3. Running with a security manager

Hibernate Validator 支持在启用 security manager 的情况下运行。为此,你必须为以下几个代码库分配多个权限:Hibernate 验证器、Jakarta Bean 验证 API、Classmate 和 JBoss Logging 以及调用 Jakarta Bean 验证的代码库。以下是通过 Java 默认策略实现处理的 policy file 实现此功能的方式:

Hibernate Validator supports running with a security manager being enabled. To do so, you must assign several permissions to the code bases of Hibernate Validator, the Jakarta Bean Validation API, Classmate and JBoss Logging and also to the code base calling Jakarta Bean Validation. The following shows how to do this via a policy file as processed by the Java default policy implementation:

示例 1.4:与安全管理器一起使用 Hibernate Validator 的策略文件

. Example 1.4: Policy file for using Hibernate Validator with a security manager

grant codeBase "file:path/to/hibernate-validator-8.0.1.Final.jar" {
    permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
    permission java.lang.RuntimePermission "accessDeclaredMembers";
    permission java.lang.RuntimePermission "setContextClassLoader";

    permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers";

    // Only needed when working with XML descriptors (validation.xml or XML constraint mappings)
    permission java.util.PropertyPermission "mapAnyUriToUri", "read";
};

grant codeBase "file:path/to/jakarta.validation-api-3.0.2.jar" {
    permission java.io.FilePermission "path/to/hibernate-validator-8.0.1.Final.jar", "read";
};

grant codeBase "file:path/to/jboss-logging-3.4.3.Final.jar" {
    permission java.util.PropertyPermission "org.jboss.logging.provider", "read";
    permission java.util.PropertyPermission "org.jboss.logging.locale", "read";
};

grant codeBase "file:path/to/classmate-1.5.1.jar" {
    permission java.lang.RuntimePermission "accessDeclaredMembers";
};

grant codeBase "file:path/to/validation-caller-x.y.z.jar" {
    permission org.hibernate.validator.HibernateValidatorPermission "accessPrivateMembers";
};

1.1.4. Updating Hibernate Validator in WildFly

WildFly application server 开箱即用地包含 Hibernate Validator。为了将 Jakarta Bean Validation API 和 Hibernate Validator 的服务器模块更新到最新版本,可以使用 WildFly 的修补机制。

The WildFly application server contains Hibernate Validator out of the box. In order to update the server modules for Jakarta Bean Validation API and Hibernate Validator to the latest and greatest, the patch mechanism of WildFly can be used.

你可以从 SourceForge 或 Maven Central 使用以下依赖项下载补丁文件:

You can download the patch file from SourceForge or from Maven Central using the following dependency:

示例 1.5:WildFly 27.0.0.Alpha4 补丁文件的 Maven 依赖项

. Example 1.5: Maven dependency for WildFly 27.0.0.Alpha4 patch file

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-modules</artifactId>
    <version>8.0.1.Final</version>
    <classifier>wildfly-27.0.0.Alpha4-patch</classifier>
    <type>zip</type>
</dependency>

我们还提供了 WildFly 的补丁:

We also provide a patch for WildFly :

示例 1.6:用于 WildFly 补丁文件的 Maven 依赖

. Example 1.6: Maven dependency for WildFly patch file

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-modules</artifactId>
    <version>8.0.1.Final</version>
    <classifier>wildfly--patch</classifier>
    <type>zip</type>
</dependency>

下载补丁文件后,可以通过运行以下命令将其应用到 WildFly:

Having downloaded the patch file, you can apply it to WildFly by running this command:

示例 1.7:应用 WildFly 补丁

. Example 1.7: Applying the WildFly patch

$JBOSS_HOME/bin/jboss-cli.sh patch apply hibernate-validator-modules-8.0.1.Final-wildfly-27.0.0.Alpha4-patch.zip

如果您想撤消补丁并返回服务器最初附带的 Hibernate Validator 版本,请运行以下命令:

In case you want to undo the patch and go back to the version of Hibernate Validator originally coming with the server, run the following command:

示例 1.8:回滚 WildFly 补丁

. Example 1.8: Rolling back the WildFly patch

$JBOSS_HOME/bin/jboss-cli.sh patch rollback --reset-configuration=true

你可以在 herehere 中详细了解 WildFly 修补基础设施。

You can learn more about the WildFly patching infrastructure in general here and here.

1.1.5. Running on Java 11+

对 Java 11 和 Java Platform Module System (JPMS) 的支持目前处于初步阶段。没有提供 JPMS 模块描述符,但 Hibernate Validator 可用作自动模块。

Support for Java 11 and the Java Platform Module System (JPMS) is present in a preliminary form. There are no JPMS module descriptors provided, but Hibernate Validator is usable as automatic modules.

以下是使用 Automatic-Module-Name 头声明的模块名称:

These are the module names as declared using the Automatic-Module-Name header:

  1. Jakarta Bean Validation API: jakarta.validation

  2. Hibernate Validator core: org.hibernate.validator

  3. Hibernate Validator CDI extension: org.hibernate.validator.cdi

  4. Hibernate Validator test utilities: org.hibernate.validator.testutils

  5. Hibernate Validator annotation processor: org.hibernate.validator.annotationprocessor

这些模块名称是初步名称,并在未来版本中提供实际模块描述符时可能会更改。

These module names are preliminary and may be changed when providing real module descriptors in a future release.

1.2. Applying constraints

让我们直接深入了解一个示例,看看如何应用约束。

Let’s dive directly into an example to see how to apply constraints.

示例 1.9:用约束进行注释的 Car 类

. Example 1.9: Class Car annotated with constraints

package org.hibernate.validator.referenceguide.chapter01;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public class Car {

    @NotNull
    private String manufacturer;

    @NotNull
    @Size(min = 2, max = 14)
    private String licensePlate;

    @Min(2)
    private int seatCount;

    public Car(String manufacturer, String licencePlate, int seatCount) {
        this.manufacturer = manufacturer;
        this.licensePlate = licencePlate;
        this.seatCount = seatCount;
    }

    //getters and setters ...
}

@NotNull@Size@Min 注释用于声明应应用于 Car 实例字段的约束:

The @NotNull, @Size and @Min annotations are used to declare the constraints which should be applied to the fields of a Car instance:

  1. manufacturer must never be null

  2. licensePlate must never be null and must be between 2 and 14 characters long

  3. seatCount must be at least 2

你可以在 GitHub 上的 Hibernate Validator source repository 中找到本参考指南中所有示例的完整源代码。

You can find the complete source code of all examples used in this reference guide in the Hibernate Validator source repository on GitHub.

1.3. Validating constraints

要验证这些约束,请使用 Validator 实例。让我们看一下 Car 的单元测试:

To perform a validation of these constraints, you use a Validator instance. Let’s have a look at a unit test for Car:

示例 1.10:展示验证示例的 CarTest 类

. Example 1.10: Class CarTest showing validation examples

package org.hibernate.validator.referenceguide.chapter01;

import java.util.Set;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;

import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class CarTest {

    private static Validator validator;

    @BeforeClass
    public static void setUpValidator() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
    }

    @Test
    public void manufacturerIsNull() {
        Car car = new Car( null, "DD-AB-123", 4 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 1, constraintViolations.size() );
        assertEquals( "must not be null", constraintViolations.iterator().next().getMessage() );
    }

    @Test
    public void licensePlateTooShort() {
        Car car = new Car( "Morris", "D", 4 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 1, constraintViolations.size() );
        assertEquals(
                "size must be between 2 and 14",
                constraintViolations.iterator().next().getMessage()
        );
    }

    @Test
    public void seatCountTooLow() {
        Car car = new Car( "Morris", "DD-AB-123", 1 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 1, constraintViolations.size() );
        assertEquals(
                "must be greater than or equal to 2",
                constraintViolations.iterator().next().getMessage()
        );
    }

    @Test
    public void carIsValid() {
        Car car = new Car( "Morris", "DD-AB-123", 2 );

        Set<ConstraintViolation<Car>> constraintViolations =
                validator.validate( car );

        assertEquals( 0, constraintViolations.size() );
    }
}

setUp() 方法中,Validator 对象是从 ValidatorFactory 中检索的。Validator 实例是线程安全的,并且可以多次重复使用。因此,可以将其安全地存储在静态字段中,并在测试方法中使用它来验证不同的 Car 实例。

In the setUp() method a Validator object is retrieved from the ValidatorFactory. A Validator instance is thread-safe and may be reused multiple times. It thus can safely be stored in a static field and be used in the test methods to validate the different Car instances.

validate() 方法返回一组 ConstraintViolation 实例,您可以遍历它们以查看发生的验证错误。前三个测试方法显示了一些预期的约束违反:

The validate() method returns a set of ConstraintViolation instances, which you can iterate over in order to see which validation errors occurred. The first three test methods show some expected constraint violations:

  1. The @NotNull constraint on manufacturer is violated in manufacturerIsNull()

  2. The @Size constraint on licensePlate is violated in licensePlateTooShort()

  3. The @Min constraint on seatCount is violated in seatCountTooLow()

如果对象验证成功,validate() 将返回一个空集,如 carIsValid() 中所示。

If the object validates successfully, validate() returns an empty set as you can see in carIsValid().

请注意,仅使用了来自 jakarta.validation 包的类。它们由 Bean Validation API 提供。没有直接引用 Hibernate Validator 的任何类,从而生成了可移植代码。

Note that only classes from the package jakarta.validation are used. These are provided from the Bean Validation API. No classes from Hibernate Validator are directly referenced, resulting in portable code.

1.4. Where to go next?

这就结束了 Hibernate Validator 和 Jakarta Bean Validation 世界的 5 分钟游览。继续探索代码示例或查看 Chapter 14, Further reading 中引用的其他示例。

That concludes the 5 minutes tour through the world of Hibernate Validator and Jakarta Bean Validation. Continue exploring the code examples or look at further examples referenced in Chapter 14, Further reading.

要了解更多有关 bean 和属性的验证,只需继续阅读 Chapter 2, Declaring and validating bean constraints 。如果您有兴趣使用 Jakarta Bean Validation 验证方法的前置条件和后置条件,请参阅 Chapter 3, Declaring and validating method constraints 。如果您的应用程序具有特定的验证要求,请查看 Chapter 6, Creating custom constraints

To learn more about the validation of beans and properties, just continue reading Chapter 2, Declaring and validating bean constraints. If you are interested in using Jakarta Bean Validation for the validation of method pre- and postcondition refer to Chapter 3, Declaring and validating method constraints. In case your application has specific validation requirements have a look at Chapter 6, Creating custom constraints.