Perbezaan Antara Kekangan @NotNull, @NotEmpty, dan @NotBlank dalam Pengesahan Kacang

1. Gambaran keseluruhan

Bean Validation adalah spesifikasi pengesahan standard yang membolehkan kita mengesahkan objek domain dengan mudah dengan menggunakan sekumpulan batasan yang dinyatakan dalam bentuk anotasi .

Walaupun secara keseluruhan, penggunaan implementasi pengesahan kacang seperti Hibernate Validator cukup mudah, perlu diterokai beberapa perbezaan halus - namun relevan - mengenai bagaimana beberapa kekangan ini dilaksanakan.

Dalam tutorial ini, kita akan melihat perbezaan antara @NotNull , @NotEmpty, dan @NotBlank kekangan .

2. Pergantungan Maven

Untuk menyediakan persekitaran kerja dengan cepat dan menguji tingkah laku kekangan @NotNull , @NotEmpty , dan @NotBlank , pertama-tama kita perlu menambahkan pergantungan Maven yang diperlukan.

Dalam kes ini, kami akan menggunakan Hibernate Validator, pelaksanaan rujukan pengesahan kacang, untuk mengesahkan objek domain kami.

Inilah bahagian yang berkaitan dengan fail pom.xml kami :

  org.hibernate hibernate-validator 6.0.13.Final   org.glassfish javax.el 3.0.0   

Kami akan menggunakan JUnit dan AssertJ dalam ujian unit kami, jadi pastikan untuk memeriksa versi terkini hibernate-validator, implementasi GlassFish's EL, junit, dan assertj-core di Maven Central.

3. Kekangan @NotNull

Melangkah ke hadapan, mari kita laksanakan kelas domain UserNotNull yang naif dan hadkan bidang namanya dengan anotasi @NotNull :

public class UserNotNull { @NotNull(message = "Name may not be null") private String name; // standard constructors / getters / toString }

Sekarang, kita perlu melihat bagaimana @NotNull sebenarnya berfungsi di bawah tudung .

Untuk melakukannya, mari buat ujian unit mudah untuk kelas dan sahkan beberapa contohnya:

@BeforeClass public static void setupValidatorInstance() { validator = Validation.buildDefaultValidatorFactory().getValidator(); } @Test public void whenNotNullName_thenNoConstraintViolations() { UserNotNull user = new UserNotNull("John"); Set
    
      violations = validator.validate(user); assertThat(violations.size()).isEqualTo(0); } @Test public void whenNullName_thenOneConstraintViolation() { UserNotNull user = new UserNotNull(null); Set
     
       violations = validator.validate(user); assertThat(violations.size()).isEqualTo(1); } @Test public void whenEmptyName_thenNoConstraintViolations() { UserNotNull user = new UserNotNull(""); Set
      
        violations = validator.validate(user); assertThat(violations.size()).isEqualTo(0); } 
      
     
    

Seperti yang dijangkakan, kekangan @NotNull tidak akan membenarkan nilai nol untuk bidang yang dikekang. Walaupun begitu, medan boleh kosong.

Untuk lebih memahami perkara ini, mari kita lihat kaedah NotNullValidator ' isValid () , yang digunakan oleh kekangan @NotNull . Pelaksanaan kaedah sangat remeh:

public boolean isValid(Object object) { return object != null; }

Seperti yang ditunjukkan di atas, medan (misalnya CharSequence , Collection , Map, atau Array) yang dibatasi dengan @NotNull mestilah tidak kosong. Walau bagaimanapun, nilai kosong betul-betul sah .

4. Kekangan @NotEmpty

Sekarang, mari kita laksanakan contoh kelas UserNotEmpty dan gunakan kekangan @NotEmpty :

public class UserNotEmpty { @NotEmpty(message = "Name may not be empty") private String name; // standard constructors / getters / toString }

Dengan kelas yang ada, mari kita mengujinya dengan memberikan nilai yang berbeza pada medan nama :

@Test public void whenNotEmptyName_thenNoConstraintViolations() { UserNotEmpty user = new UserNotEmpty("John"); Set
    
      violations = validator.validate(user); assertThat(violations.size()).isEqualTo(0); } @Test public void whenEmptyName_thenOneConstraintViolation() { UserNotEmpty user = new UserNotEmpty(""); Set
     
       violations = validator.validate(user); assertThat(violations.size()).isEqualTo(1); } @Test public void whenNullName_thenOneConstraintViolation() { UserNotEmpty user = new UserNotEmpty(null); Set
      
        violations = validator.validate(user); assertThat(violations.size()).isEqualTo(1); }
      
     
    

The @NotEmpty jenama anotasi menggunakan daripada @NotNull kelas ' isValid () pelaksanaan dan tambahan cek saiz / panjang objek dibekalkan (sudah tentu, ini berbeza-beza mengikut jenis objek yang disahkan) adalah lebih besar daripada sifar.

Ringkasnya, ini bermaksud bahawa medan (misalnya CharSequence , Collection , Map, atau Array) yang dibatasi dengan @NotEmpty tidak boleh kosong dan ukuran / panjangnya mestilah lebih besar daripada sifar .

Selain itu, kita boleh menjadi lebih ketat jika kita menggunakan anotasi @NotEmpty bersama dengan @Size.

Dengan berbuat demikian, kami juga menegaskan bahawa nilai ukuran minimum dan maksimum objek berada dalam julat min / maks yang ditentukan:

@NotEmpty(message = "Name may not be empty") @Size(min = 2, max = 32, message = "Name must be between 2 and 32 characters long") private String name; 

5. Kekangan @NotBlank

Begitu juga, kita boleh mengekang medan kelas dengan anotasi @NotBlank :

public class UserNotBlank { @NotBlank(message = "Name may not be blank") private String name; // standard constructors / getters / toString }

Sejalan dengan itu, kita dapat melaksanakan ujian unit untuk memahami bagaimana kekangan @NotBlank berfungsi:

@Test public void whenNotBlankName_thenNoConstraintViolations() { UserNotBlank user = new UserNotBlank("John"); Set
    
      violations = validator.validate(user); assertThat(violations.size()).isEqualTo(0); } @Test public void whenBlankName_thenOneConstraintViolation() { UserNotBlank user = new UserNotBlank(" "); Set
     
       violations = validator.validate(user); assertThat(violations.size()).isEqualTo(1); } @Test public void whenEmptyName_thenOneConstraintViolation() { UserNotBlank user = new UserNotBlank(""); Set
      
        violations = validator.validate(user); assertThat(violations.size()).isEqualTo(1); } @Test public void whenNullName_thenOneConstraintViolation() { UserNotBlank user = new UserNotBlank(null); Set
       
         violations = validator.validate(user); assertThat(violations.size()).isEqualTo(1); } 
       
      
     
    

The @NotBlank anotasi menggunakan NotBlankValidator kelas, yang cek yang panjang dipotong urutan watak itu tidak kosong:

public boolean isValid( CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) if (charSequence == null ) { return true; } return charSequence.toString().trim().length() > 0; } 

Cukup lucu, kaedah ini kembali benar untuk nilai nol. Jadi, kami mungkin berpendapat bahawa @NotBlank membenarkan nilai nol, tetapi sebenarnya tidak.

The @NotNull kelas 'kaedah isValid () dipanggil selepas @NotBlank kelas' isValid (), oleh itu melarang nilai null.

Untuk meletakkan ia hanya, yang String bidang dikekang dengan @NotBlank mesti tidak batal dan panjang dipotong mesti lebih besar daripada sifar .

6. Perbandingan Berdampingan

Setakat ini, kami telah melihat secara mendalam bagaimana kekangan @NotNull , @NotEmpty , dan @NotBlank beroperasi secara individu di medan kelas.

Mari kita buat perbandingan berdampingan dengan cepat, supaya kita dapat melihat fungsi kekangan dan melihat perbezaannya dengan mudah:

  • @NotNull: CharSequence , Collection , Map, atau Array yang dibatasi adalah sah selagi tidak kosong, tetapi boleh kosong
  • @NotEmpty: CharSequence , Collection , Map, atau Array yang dibatasi adalah sah selagi tidak kosong dan ukuran / panjangnya lebih besar daripada sifar
  • @NotBlank: String yang dibatasi berlaku selagi tidak kosong dan panjang yang dipangkas lebih besar daripada sifar

7. Kesimpulannya

Dalam artikel ini, kami melihat kekangan NotNull , @NotEmpty , dan @NotBlank yang dilaksanakan dalam Bean Validation dan menunjukkan persamaan dan perbezaan mereka.

Seperti biasa, semua contoh kod yang ditunjukkan dalam artikel ini terdapat di GitHub.