Hibernate Validator Specific Constraints – Hibernate验证器的具体约束条件

最后修改: 2019年 6月 9日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’re going to review Hibernate Validator constraints, which are built into Hibernate Validator but are outside the Bean Validation spec.

在本教程中,我们将回顾Hibernate Validator的约束条件,这些约束条件内置于Hibernate Validator中,但在Bean Validation规范之外。

For a recap of Bean Validation, please refer to our article on Java Bean Validation Basics.

关于Bean Validation的回顾,请参考我们的文章Java Bean Validation Basics

2. Hibernate Validator Setup

2.Hibernate验证器的设置

At the very least, we should add Hibernate Validator to our dependencies:

至少,我们应该将Hibernate Validator添加到我们的依赖项中:

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

Note that Hibernate Validator does not depend on Hibernate, the ORM, which we’ve covered in many other articles.

请注意,Hibernate验证器并不依赖于Hibernate这个ORM,我们已经在其他许多文章中介绍过。

Additionally, some of the annotations that we’ll introduce only apply if our project makes use of certain libraries. So, for each one of those, we’ll indicate the necessary dependencies.

此外,我们将引入的一些注释只适用于我们的项目使用某些库的情况。因此,对于其中的每一个,我们将指出必要的依赖关系。

3. Validating Money-related Values

3.验证与金钱有关的价值

3.1. Validating Credit Card Numbers

3.1.验证信用卡号码

Valid credit card numbers must satisfy a checksum, which we compute using Luhn’s Algorithm. The @CreditCardNumber constraint succeeds when a string satisfies the checksum.

有效的信用卡号码必须满足一个校验和,我们使用Luhn的算法来计算。当一个字符串满足校验和时,@CreditCardNumber约束成功。

@CreditCardNumber does not perform any other check on the input string. In particular, it doesn’t check the length of the input. Therefore, it can only detect numbers that are invalid due to a small typo.

@CreditCardNumber不对输入的字符串进行任何其他检查。特别是,它不检查输入的长度。因此,它只能检测出由于一个小的错字而导致的无效数字。

Note that, by default, the constraint fails if the string contains characters which aren’t digits, but we can tell it to ignore them:

注意,默认情况下,如果字符串中包含非数字的字符,则约束失败,但我们可以告诉它忽略它们。

@CreditCardNumber(ignoreNonDigitCharacters = true)
private String lenientCreditCardNumber;

Then, we can include characters such as spaces or dashes:

然后,我们可以包括诸如空格或破折号等字符。

validations.setLenientCreditCardNumber("7992-7398-713");
constraintViolations = validator.validateProperty(validations, "lenientCreditCardNumber");
assertTrue(constraintViolations.isEmpty());

3.2. Validating Monetary Values

3.2.验证货币价值

The @Currency validator checks whether a given monetary amount is in the specified currency:

@Currency验证器检查一个给定的货币金额是否是指定的货币。

@Currency("EUR")
private MonetaryAmount balance;

The class MonetaryAmount is part of Java Money. Therefore, @Currency only applies when a Java Money implementation is available.

MonetaryAmount是Java Money的一部分。因此,@Currency 只适用于当有Java Money实现时.

Once we have set Java Money up correctly, we can check the constraint:

一旦我们正确设置了Java Money,我们就可以检查约束。

bean.setBalance(Money.of(new BigDecimal(100.0), Monetary.getCurrency("EUR")));
constraintViolations = validator.validateProperty(bean, "balance");
assertEquals(0, constraintViolations.size());

4. Validating Ranges

4.验证区间

4.1. Numeric and Monetary Ranges

4.1.数值和货币范围

The bean validation specification defines several constraints which we can enforce on numeric fields. Besides those, Hibernate Validator provides a handy annotation, @Range, that acts as a combination of @Min and @Max, matching a range inclusively:

Bean验证规范定义了几个约束条件,我们可以在数字字段上强制执行。除了这些,Hibernate验证器还提供了一个方便的注解,@Range作为@Min@Max的组合,对一个范围进行全面匹配。

@Range(min = 0, max = 100)
private BigDecimal percent;

Like @Min and @Max, @Range is applicable on fields of primitive number types and their wrappers; BigInteger and BigDecimalString representations of the above, and, finally, MonetaryValue fields.

@Min@Max一样,@Range适用于原始数字类型的字段和它们的封装器;BigIntegerBigDecimal,上述的String表示,以及最后,MonetaryValue字段。

4.2. Duration of Time

4.2.时间的长短

In addition to standard JSR 380 annotations for values that represent points in time, Hibernate Validator includes constraints for Durations as well. Make sure to check out the Period and Duration classes of Java Time first.

除了代表时间点的标准JSR380注释外,Hibernate验证器还包括对Durations的约束。请确保首先查看Java Time的Period Duration 类。

So, we can enforce minimum and maximum durations on a property:

因此,我们可以在一个属性上执行最小和最大的期限:

@DurationMin(days = 1, hours = 2)
@DurationMax(days = 2, hours = 1)
private Duration duration;

Even if we didn’t show them all here, the annotation has parameters for all units of time from nanoseconds to days.

即使我们没有在这里全部显示出来,注释中也有从纳秒到天的所有时间单位的参数。

Please note that, by default, minimum and maximum values are inclusive. That is, a value which is exactly the same as the minimum or the maximum will pass validation.

请注意,默认情况下,最小值和最大值是包括在内的。也就是说,一个与最小值或最大值完全相同的值将通过验证。

If we want boundary values to be invalid, instead, we define the inclusive property to be false:

如果我们希望边界值是无效的,相反,我们将inclusive属性定义为false。

@DurationMax(minutes = 30, inclusive = false)

5. Validating Strings

5.验证字符串

5.1. String Length

5.1.字符串长度

We can use two slightly different constraints to enforce that a string is of a certain length.

我们可以使用两个略有不同的约束条件来强制要求一个字符串具有一定的长度。

Generally, we’ll want to ensure a string’s length in characters – the one we measure with the length method – is between a minimum and a maximum. In that case, we use @Length on a String property or field:

一般来说,我们要确保一个字符串的长度(即我们用length 方法测量的长度)在最小和最大之间。在这种情况下,我们在一个字符串属性或字段上使用@Length

@Length(min = 1, max = 3)
private String someString;

However, due to the intricacies of Unicode, sometimes the length in characters and the length in code points differ. When we want to check the latter, we use @CodePointLength:

然而,由于Unicode的复杂性,有时字符的长度和代码点的长度是不同的。当我们想检查后者时,我们使用@CodePointLength:

@CodePointLength(min = 1, max = 3)
private String someString;

For example, the string “aa\uD835\uDD0A” is 4 characters long, but it contains only 3 code points, so it’ll fail the first constraint and pass the second one.

例如,字符串 “aa\uD835\uDD0A “有4个字符长,但它只包含3个代码点,所以它将无法通过第一个约束,而通过第二个约束。

Also, with both annotations, we can omit the minimum or the maximum value.

另外,对于这两个注释,我们可以省略最小值或最大值。

5.2. Checks on Strings of Digits

5.2.对数字串的校验

We’ve already seen how to check that a string is a valid credit card number. However, Hibernate Validator includes several other constraints for strings of digits.

我们已经看到了如何检查一个字符串是否是有效的信用卡号码。然而,Hibernate验证器还包括了其他几种对数字字符串的约束。

The first one we’re reviewing is @LuhnCheck. This is the generalized version of @CreditCardNumber, in that it performs the same check, but allows for additional parameters:

我们要审查的第一个项目是@LuhnCheck。这是@CreditCardNumber的普及版,因为它执行相同的检查,但允许附加参数:

@LuhnCheck(startIndex = 0, endIndex = Integer.MAX_VALUE, checkDigitIndex = -1)
private String someString;

Here, we’ve shown the default values of the parameters, so the above is equivalent to a simple @LuhnCheck annotation.

在这里,我们显示了参数的默认值,因此上述内容相当于一个简单的@LuhnCheck注释。

But, as we can see, we can perform the check on a substring (startIndex and endIndex) and tell the constraint which digit is the checksum digit, with -1 meaning the last one in the checked substring.

但是,正如我们所看到的,我们可以对一个子串(startIndexendIndex)进行检查,并告诉约束哪个数字是校验码,-1意味着被检查子串中的最后一个数字。

Other interesting constraints include the modulo 10 check (@Mod10Check) and the modulo 11 check (@Mod11Check), which are typically used for barcodes and other codes such as ISBN.

其他有趣的约束包括模10检查@Mod10Check)和模11检查@Mod11Check),它们通常用于条形码和其他代码,如ISBN。

However, for those specific cases, Hibernate Validator happens to provide a constraint to validate ISBN codes, @ISBN, as well as an @EAN constraint for EAN barcodes.

然而,对于这些特殊情况,Hibernate验证器恰好提供了一个验证ISBN代码的约束,@ISBN,以及一个针对EAN条形码的@EAN约束。

5.3. URL and HTML Validation

5.3.URL和HTML验证

The @Url constraint verifies that a string is a valid representation of a URL. Additionally, we can check that specific component of the URL has a certain value:

@Url约束验证了一个字符串是一个URL的有效表示。此外,我们还可以检查URL的特定组件是否具有某种值。

@URL(protocol = "https")
private String url;

We can thus check the protocol, the host and the port. If that’s not sufficient, there’s a regexp property that we can use to match the URL against a regular expression.

因此,我们可以检查协议、主机和端口。如果这还不够,还有一个regexp属性,我们可以用它来匹配URL与正则表达式。

We can also verify that a property contains “safe” HTML code (for example, without script tags):

我们还可以验证一个属性是否包含 “安全 “的HTML代码(例如,没有脚本标签)。

@SafeHtml
private String html;

@SafeHtml uses the JSoup library, which must be included in our dependencies.

@SafeHtml 使用JSoup库,它必须被包含在我们的依赖中。

We can tailor the HTML sanitization to our needs using built-in tag whitelists (the whitelist property of the annotation) and including additional tags and attributes (the additionalTags and additionalTagsWithAttributes parameters).

我们可以使用内置的标签白名单(注释的whitelist属性)和包括额外的标签和属性(additionalTagsadditionalTagsWithAttributes参数),根据我们的需要定制HTML净化。

6. Other Constraints

6.其他制约因素

Let’s mention briefly that Hibernate Validator includes some country and locale-specific constraints, in particular for some Brazilian and Polish identification numbers, taxpayer codes and similar. Please refer to the relevant section of the documentation for a full list.

让我们简单提一下,Hibernate验证器包括一些国家和地方的特定约束,特别是对一些巴西和波兰的身份证号码、纳税人代码和类似的约束。请参考文档的相关部分以获得完整的列表。

Also, we can check that a collection does not contain duplicates with @UniqueElements.

另外,我们可以用@UniqueElements.来检查一个集合是否包含重复的内容。

Finally, for complex cases not covered by existing annotations, we can invoke a script written in a JSR-223 compatible scripting engine. We’ve, of course, touched on JSR-223 in our article about Nashorn, the JavaScript implementation included in modern JVMs.

最后,对于现有注解没有涵盖的复杂情况,我们可以调用一个用JSR-223兼容的脚本引擎编写的脚本。当然,我们已经在我们关于Nashorn的文章中提到了JSR-223,这是现代JVM中包含的JavaScript实现。

In this case, the annotation is at the class level, and the script is invoked on the entire instance, passed as the variable _this:

在这种情况下,注释是在类的层面上,脚本在整个实例上被调用,作为变量_this:传递。

@ScriptAssert(lang = "nashorn", script = "_this.valid")
public class AdditionalValidations {
    private boolean valid = true;
    // standard getters and setters
}

Then, we can check the constraint on the whole instance:

然后,我们可以检查整个实例的约束条件。

bean.setValid(false);
constraintViolations = validator.validate(bean);
assertEquals(1, constraintViolations.size());

7. Conclusion

7.结论

In this article, we’ve listed the constraints in Hibernate Validator that go beyond the minimal set defined in the Bean Validation specification.

在这篇文章中,我们列出了Hibernate验证器中的约束,这些约束超出了Bean Validation规范中定义的最小集合。

The implementation of all these examples and code snippets can be found over on GitHub.

所有这些例子和代码片断的实现都可以在GitHub上找到over