Kekangan Spesifik Hibernate Validator

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan mengkaji kekangan Hibernate Validator, yang terdapat di dalam Hibernate Validator tetapi berada di luar spesifikasi Bean Validation

Untuk rangkuman Validasi Kacang, rujuk artikel kami mengenai Asas Pengesahan Kacang Jawa.

2. Persediaan Hibernate Validator

Paling tidak, kita harus menambahkan Hibernate Validator ke tanggungan kita:

 org.hibernate.validator hibernate-validator 6.0.16.Final 

Perhatikan bahawa Hibernate Validator tidak bergantung pada Hibernate, ORM, yang telah kami bahas dalam banyak artikel lain.

Selain itu, beberapa anotasi yang akan kami perkenalkan hanya berlaku jika projek kami menggunakan perpustakaan tertentu. Oleh itu, untuk masing-masing, kami akan menunjukkan kebergantungan yang diperlukan.

3. Mengesahkan Nilai Berkaitan Wang

3.1. Mengesahkan Nombor Kad Kredit

Nombor kad kredit yang sah mesti memenuhi checksum, yang kami hitung menggunakan Algoritma Luhn. The @CreditCardNumber kekangan berjaya apabila rentetan memenuhi checksum.

@CreditCardNumber tidak melakukan pemeriksaan lain pada rentetan input. Khususnya, ia tidak memeriksa panjang input. Oleh itu, ia hanya dapat mengesan nombor yang tidak sah kerana kesalahan ketik kecil.

Perhatikan bahawa, secara lalai, kekangan gagal jika rentetan mengandungi aksara yang bukan digit, tetapi kami dapat memintanya untuk mengabaikannya:

@CreditCardNumber(ignoreNonDigitCharacters = true) private String lenientCreditCardNumber;

Kemudian, kita boleh memasukkan watak seperti spasi atau tanda sempang:

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

3.2. Mengesahkan Nilai Wang

The @Currency cek validator sama ada jumlah wang yang diberi adalah dalam mata wang yang dinyatakan:

@Currency("EUR") private MonetaryAmount balance;

Kelas MonetaryAmount adalah sebahagian daripada Wang Java. Oleh itu, @Currency hanya berlaku ketika implementasi Java Money tersedia.

Setelah kami menetapkan Java Money dengan betul, kami dapat memeriksa kekangannya:

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

4. Mengesahkan Julat

4.1. Julat Numerik dan Monetari

Spesifikasi pengesahan kacang menentukan beberapa kekangan yang dapat kita tegakkan pada bidang angka. Selain itu, Hibernate Validator memberikan anotasi yang berguna, @Range , yang bertindak sebagai gabungan antara @Min dan @Max, yang sesuai dengan julat:

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

Seperti @Min dan @Max , @Range berlaku pada bidang jenis nombor primitif dan pembungkus mereka; BigInteger dan BigDecimal , String representasi di atas, dan akhirnya bidang MonetaryValue .

4.2. Tempoh Masa

Sebagai tambahan kepada penjelasan standard JSR 380 untuk nilai-nilai yang mewakili titik waktu, Hibernate Validator juga menyertakan batasan untuk Tempoh . Pastikan anda melihat kelas Period dan Tempoh Masa Java terlebih dahulu.

Oleh itu, kami dapat melaksanakan jangka masa minimum dan maksimum pada harta tanah

@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:

@DurationMax(minutes = 30, inclusive = false)

5. Validating Strings

5.1. String Length

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(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:

@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.

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

5.2. Checks on Strings of Digits

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.

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(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.

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.

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.

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.

5.3. URL and HTML Validation

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(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.

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

@SafeHtml private String html;

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

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).

6. Other Constraints

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.

Also, we can check that a collection does not contain duplicates with @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.

In this case, the annotation is at the class level, and the script is invoked on the entire instance, passed as the variable _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. Kesimpulannya

Dalam artikel ini, kami telah menyenaraikan batasan dalam Hibernate Validator yang melampaui set minimum yang ditentukan dalam spesifikasi Bean Validation.

Pelaksanaan semua contoh dan coretan kod ini boleh didapati di GitHub.