1. Общ преглед
Bean Validation е стандартна спецификация за проверка, която ни позволява лесно да проверяваме обектите на домейна, като използваме набор от ограничения, декларирани под формата на пояснения .
Макар че като цяло използването на изпълненията за проверка на боб като Hibernate Validator е доста просто, струва си да се проучат някои фини - но съществени - разлики относно това как някои от тези ограничения се прилагат.
В този урок ние ще забележите разликите между @NotNull , @NotEmpty, и @NotBlank ограничения .
2. Зависимостите на Maven
За да настроим бързо работна среда и да тестваме поведението на ограниченията @NotNull , @NotEmpty и @NotBlank , първо трябва да добавим необходимите зависимости на Maven.
В този случай ще използваме Hibernate Validator, референтната имплементация на бин за валидиране на обектите на домейна ни.
Ето съответния раздел от нашия файл pom.xml :
org.hibernate hibernate-validator 6.0.13.Final org.glassfish javax.el 3.0.0
Ще използваме JUnit и AssertJ в нашите модулни тестове, така че не забравяйте да проверите най-новите версии на hibernate-validator, изпълнението на GlassFish EL, junit и assertj-core на Maven Central.
3. Ограничението @NotNull
Движейки се напред, нека да приложи наивен UserNotNull клас домейн и ограничи неговото име поле с @NotNull анотация:
public class UserNotNull { @NotNull(message = "Name may not be null") private String name; // standard constructors / getters / toString }
Сега трябва да видим как всъщност работи @NotNull под капака .
За целта нека създадем прост единичен тест за класа и да проверим няколко негови екземпляра:
@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); }
Както се очаква, ограничението @NotNull няма да позволи нулеви стойности за ограничените полета. Въпреки това полето (ите) може да е празно.
За да разберем по-добре това, нека разгледаме метода на клас NotNullValidator ' isValid () , който ограничението @NotNull използва. Изпълнението на метода е наистина тривиално:
public boolean isValid(Object object) { return object != null; }
Както е показано по-горе, поле (напр. CharSequence , Collection , Map или Array), ограничено с @NotNull, не трябва да е null. Празната стойност обаче е напълно законна .
4. Ограничението @NotEmpty
Сега, нека внедрим примерен клас UserNotEmpty и използваме ограничението @NotEmpty :
public class UserNotEmpty { @NotEmpty(message = "Name may not be empty") private String name; // standard constructors / getters / toString }
С клас на място, нека просто да го тестваме, като присвоим различни стойности на полето за име :
@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); }
На @NotEmpty марките анотация използването на @NotNull класа " isValid () прилагане и допълнително проверки, че размер / дължина на приложената обекта (разбира се, това варира в зависимост от вида на обекта се валидира) е по-голяма от нула.
Накратко, това означава, че поле (напр. CharSequence , Collection , Map или Array), ограничено с @NotEmpty, не трябва да е null и неговият размер / дължина трябва да бъде по-голямо от нула .
Освен това можем да бъдем още по-ограничителни, ако използваме анотацията @NotEmpty заедно с @Size.
По този начин бихме принудили също така, че минималните и максималните размери на обекта са в рамките на посочения минимален / максимален диапазон:
@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. Ограничението @NotBlank
По подобен начин можем да ограничим поле на клас с анотацията @NotBlank :
public class UserNotBlank { @NotBlank(message = "Name may not be blank") private String name; // standard constructors / getters / toString }
По същия начин можем да приложим единичен тест, за да разберем как работи ограничението @NotBlank :
@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); }
В @NotBlank анотацията използва NotBlankValidator класа, която проверява дали почиства дължина на поредица от знаци не се изпразни:
public boolean isValid( CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) if (charSequence == null ) { return true; } return charSequence.toString().trim().length() > 0; }
Забавно, методът връща вярно за нулеви стойности. Така че, може да си помислим, че @NotBlank разрешава нулеви стойности, но всъщност не.
В @NotNull клас "метод isValid () се нарича след @NotBlank класа" isValid (), следователно забранява нула стойности.
По-просто казано, един низ поле ограничени с @NotBlank трябва да бъде не нищожно и почиства дължината трябва да бъде по-голяма от нула .
6. Сравнение едно до друго
Досега разгледахме задълбочено как ограниченията @NotNull , @NotEmpty и @NotBlank действат индивидуално в полетата на класа.
Нека направим бързо сравнение едно до друго, за да можем да видим от птичи поглед функционалността на ограниченията и лесно да забележим разликите им:
- @NotNull: ограничена CharSequence , Collection , Map или Array е валидна, стига да не е null, но може да е празна
- @NotEmpty: ограничена CharSequence , Collection , Map или Array е валидна, стига да не е нула и размерът / дължината й да е по-голяма от нула
- @NotBlank: ограниченият низ е валиден, стига да не е нула и отрязаната дължина е по-голяма от нула
7. Заключение
В тази статия разгледахме ограниченията NotNull , @NotEmpty и @NotBlank , внедрени в Bean Validation, и подчертахме техните прилики и разлики.
Както обикновено, всички примерни кодове, показани в тази статия, са достъпни в GitHub.