Batasan Khusus Hibernate Validator

1. Ikhtisar

Dalam tutorial ini, kita akan meninjau batasan Hibernate Validator, yang dibangun ke dalam Hibernate Validator tetapi berada di luar spesifikasi Validasi Bean.

Untuk rekap Validasi Bean, lihat artikel kami di Dasar-Dasar Validasi Bean Java.

2. Pengaturan Validator Hibernasi

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

 org.hibernate.validator hibernate-validator 6.0.16.Final 

Perhatikan bahwa Hibernate Validator tidak bergantung pada Hibernate, ORM, yang telah kita bahas di banyak artikel lainnya.

Selain itu, beberapa anotasi yang akan kami perkenalkan hanya berlaku jika proyek kami menggunakan pustaka tertentu. Jadi, untuk masing-masing, kami akan menunjukkan dependensi yang diperlukan.

3. Memvalidasi Nilai Terkait Uang

3.1. Memvalidasi Nomor Kartu Kredit

Nomor kartu kredit yang valid harus memenuhi checksum, yang kami hitung menggunakan Algoritma Luhn. The @CreditCardNumber kendala berhasil ketika tali memenuhi checksum.

@CreditCardNumber tidak melakukan pemeriksaan lain pada string input. Secara khusus, itu tidak memeriksa panjang input. Oleh karena itu, ini hanya dapat mendeteksi nomor yang tidak valid karena kesalahan ketik kecil.

Perhatikan bahwa, secara default, batasan gagal jika string berisi karakter yang bukan digit, tetapi kita dapat menyuruhnya untuk mengabaikannya:

@CreditCardNumber(ignoreNonDigitCharacters = true) private String lenientCreditCardNumber;

Kemudian, kita dapat memasukkan karakter seperti spasi atau tanda hubung:

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

3.2. Memvalidasi Nilai Moneter

The @Currency validator memeriksa apakah jumlah moneter yang diberikan adalah dalam mata uang tertentu:

@Currency("EUR") private MonetaryAmount balance;

Kelas MonetaryAmount adalah bagian dari Java Money. Oleh karena itu, @Currency hanya berlaku jika implementasi Java Money tersedia.

Setelah kami menyiapkan Java Money dengan benar, kami dapat memeriksa batasannya:

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

4. Memvalidasi Rentang

4.1. Rentang Numerik dan Moneter

Spesifikasi validasi bean mendefinisikan beberapa batasan yang dapat kita terapkan pada field numerik. Selain itu, Hibernate Validator menyediakan anotasi praktis, @Range , yang bertindak sebagai kombinasi @Min dan @Max, mencocokkan rentang secara inklusif:

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

Seperti @Min dan @Max , @Range berlaku pada bidang tipe angka primitif dan pembungkusnya; BigInteger dan BigDecimal , representasi String di atas, dan, terakhir, bidang MonetaryValue .

4.2. Durasi Waktu

Selain anotasi JSR 380 standar untuk nilai-nilai yang mewakili titik waktu, Hibernate Validator juga menyertakan batasan untuk Durasi . Pastikan untuk memeriksa kelas Periode dan Durasi Waktu Java terlebih dahulu.

Jadi, kami dapat menerapkan durasi minimum dan maksimum pada sebuah properti:

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

Meskipun kami tidak menampilkan semuanya di sini, anotasi memiliki parameter untuk semua unit waktu dari nanodetik hingga hari.

Harap dicatat bahwa, secara default, nilai minimum dan maksimum sudah termasuk. Artinya, nilai yang sama persis dengan minimum atau maksimum akan lolos validasi.

Jika kita ingin nilai batas menjadi tidak valid, kita mendefinisikan properti inklusif menjadi salah:

@DurationMax(minutes = 30, inclusive = false)

5. Memvalidasi String

5.1. Panjang String

Kita dapat menggunakan dua batasan yang sedikit berbeda untuk memaksakan bahwa sebuah string memiliki panjang tertentu.

Umumnya, kami ingin memastikan panjang string dalam karakter - yang kami ukur dengan metode panjang - adalah antara minimum dan maksimum. Dalam hal ini, kami menggunakan @Length pada properti atau bidang String:

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

Namun, karena kerumitan Unicode, terkadang panjang karakter dan panjang poin kode berbeda. Saat kami ingin memeriksa yang terakhir, kami menggunakan @CodePointLength:

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

Misalnya, string "aa \ uD835 \ uDD0A" memiliki 4 karakter, tetapi hanya berisi 3 poin kode, jadi itu akan gagal pada batasan pertama dan melewati batasan kedua.

Selain itu, dengan kedua anotasi, kita dapat menghilangkan nilai minimum atau maksimum.

5.2. Mengecek String of Digit

Kami telah melihat cara memeriksa bahwa string adalah nomor kartu kredit yang valid. Namun, Hibernate Validator menyertakan beberapa batasan lain untuk string digit.

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

Pada artikel ini, kami telah membuat daftar batasan dalam Hibernate Validator yang melampaui set minimal yang ditentukan dalam spesifikasi Validasi Bean.

Penerapan semua contoh dan cuplikan kode ini dapat ditemukan di GitHub.