1. введение
В нашем учебнике Основы проверки компонентов Java мы видели использование различных встроенных ограничений javax.validation . В этом уроке мы увидим как группировать javax.validation ограничения .
2. Пример использования
Существует множество сценариев, в которых нам нужно применить ограничения к определенному набору полей компонента, а затем позже мы хотим применить ограничения к другому набору полей того же компонента.
Например, давайте представим, что у нас есть двухэтапная форма регистрации. На первом этапе мы просим пользователя предоставить основную информацию, такую как имя, фамилия, идентификатор электронной почты, номер телефона и капчу. Когда пользователь отправляет эти данные, мы хотим проверить только эту информацию.
На следующем шаге мы просим пользователя предоставить некоторую другую информацию, например адрес, и мы также хотим проверить эту информацию — обратите внимание, что капча присутствует на обоих шагах.
3. Ограничения проверки группирования
Все ограничения проверки javax имеют атрибут с именем groups . Когда мы добавляем ограничение к элементу, мы можем объявить имя группы, к которой принадлежит ограничение. Это делается путем указания имени класса интерфейса группы в атрибутах groups ограничения.
Лучший способ понять что-то-это испачкать руки. Давайте посмотрим в действии, как мы объединяем ограничения javax в группы.
3.1. Объявление групп ограничений
Первым шагом является создание некоторых интерфейсов. Эти интерфейсы будут именами групп ограничений. В нашем случае мы разделяем ограничения проверки на две группы.
Давайте посмотрим на первую группу ограничений, Основная информация :
public interface BasicInfo { }
Следующая группа ограничений – Предварительная информация :
public interface AdvanceInfo { }
3.2. Использование групп Ограничений
Теперь, когда мы объявили наши группы ограничений, пришло время использовать их в нашей Регистрационной форме Javabean:
public class RegistrationForm { @NotBlank(groups = BasicInfo.class) private String firstName; @NotBlank(groups = BasicInfo.class) private String lastName; @Email(groups = BasicInfo.class) private String email; @NotBlank(groups = BasicInfo.class) private String phone; @NotBlank(groups = {BasicInfo.class, AdvanceInfo.class}) private String captcha; @NotBlank(groups = AdvanceInfo.class) private String street; @NotBlank(groups = AdvanceInfo.class) private String houseNumber; @NotBlank(groups = AdvanceInfo.class) private String zipCode; @NotBlank(groups = AdvanceInfo.class) private String city; @NotBlank(groups = AdvanceInfo.class) private String contry; }
С помощью атрибута constraint groups мы разделили поля нашего компонента на две группы в соответствии с нашим вариантом использования. По умолчанию все ограничения включены в группу ограничений по умолчанию.
3.3. Тестирование Ограничений, Имеющих Одну Группу
Теперь, когда мы объявили группы ограничений и использовали их в нашем классе bean, пришло время увидеть эти группы ограничений в действии.
Во-первых, мы увидим, когда основная информация не будет полной, используя нашу группу ограничений Basic Info для проверки. Мы должны получить нарушение ограничений для любого поля, оставленного пустым там, где мы использовали BasicInfo.class в атрибуте groups ограничения поля @NotBlank :
public class RegistrationFormUnitTest { private static Validator validator; @BeforeClass public static void setupValidatorInstance() { validator = Validation.buildDefaultValidatorFactory().getValidator(); } @Test public void whenBasicInfoIsNotComplete_thenShouldGiveConstraintViolationsOnlyForBasicInfo() { RegistrationForm form = buildRegistrationFormWithBasicInfo(); form.setFirstName(""); Set> violations = validator.validate(form, BasicInfo.class); assertThat(violations.size()).isEqualTo(1); violations.forEach(action -> { assertThat(action.getMessage()).isEqualTo("must not be blank"); assertThat(action.getPropertyPath().toString()).isEqualTo("firstName"); }); } private RegistrationForm buildRegistrationFormWithBasicInfo() { RegistrationForm form = new RegistrationForm(); form.setFirstName("devender"); form.setLastName("kumar"); form.setEmail("[email protected]"); form.setPhone("12345"); form.setCaptcha("Y2HAhU5T"); return form; } //... additional tests }
В следующем сценарии мы проверим, является ли дополнительная информация неполной, используя нашу группу ограничений Advance Info для проверки:
@Test public void whenAdvanceInfoIsNotComplete_thenShouldGiveConstraintViolationsOnlyForAdvanceInfo() { RegistrationForm form = buildRegistrationFormWithAdvanceInfo(); form.setZipCode(""); Set> violations = validator.validate(form, AdvanceInfo.class); assertThat(violations.size()).isEqualTo(1); violations.forEach(action -> { assertThat(action.getMessage()).isEqualTo("must not be blank"); assertThat(action.getPropertyPath().toString()).isEqualTo("zipCode"); }); } private RegistrationForm buildRegistrationFormWithAdvanceInfo() { RegistrationForm form = new RegistrationForm(); return populateAdvanceInfo(form); } private RegistrationForm populateAdvanceInfo(RegistrationForm form) { form.setCity("Berlin"); form.setContry("DE"); form.setStreet("alexa str."); form.setZipCode("19923"); form.setHouseNumber("2a"); form.setCaptcha("Y2HAhU5T"); return form; }
3.4. Тестирование Ограничений, Имеющих Несколько Групп
Мы можем указать несколько групп для ограничения. В нашем случае мы используем captcha как в базовой, так и в расширенной информации. Давайте сначала протестируем captcha с Базовой информацией :
@Test public void whenCaptchaIsBlank_thenShouldGiveConstraintViolationsForBasicInfo() { RegistrationForm form = buildRegistrationFormWithBasicInfo(); form.setCaptcha(""); Set> violations = validator.validate(form, BasicInfo.class); assertThat(violations.size()).isEqualTo(1); violations.forEach(action -> { assertThat(action.getMessage()).isEqualTo("must not be blank"); assertThat(action.getPropertyPath().toString()).isEqualTo("captcha"); }); }
Теперь давайте проверим captcha с Предварительная информация :
@Test public void whenCaptchaIsBlank_thenShouldGiveConstraintViolationsForAdvanceInfo() { RegistrationForm form = buildRegistrationFormWithAdvanceInfo(); form.setCaptcha(""); Set> violations = validator.validate(form, AdvanceInfo.class); assertThat(violations.size()).isEqualTo(1); violations.forEach(action -> { assertThat(action.getMessage()).isEqualTo("must not be blank"); assertThat(action.getPropertyPath().toString()).isEqualTo("captcha"); }); }
4. Указание порядка проверки группы ограничений с последовательностью групп
По умолчанию группы ограничений не оцениваются в каком-либо определенном порядке. Но у нас могут быть случаи использования, когда некоторые группы должны быть проверены раньше других. Для достижения этой цели мы можем указать порядок проверки группы, используя Последовательность групп.
Существует два способа использования аннотации GroupSequence :
- о проверяемом объекте
- на интерфейсе
4.1. Использование групповой последовательности на Проверяемом объекте
Это простой способ упорядочения ограничений. Давайте аннотируем сущность с помощью Групповой последовательности и определим порядок ограничений:
@GroupSequence({BasicInfo.class, AdvanceInfo.class}) public class RegistrationForm { @NotBlank(groups = BasicInfo.class) private String firstName; @NotBlank(groups = AdvanceInfo.class) private String street; }
4.2. Использование групповой последовательности на интерфейсе
Мы также можем указать порядок проверки ограничений с помощью интерфейса |. Преимущество этого подхода заключается в том, что та же последовательность может быть использована для других объектов. Давайте посмотрим, как мы можем использовать Групповую последовательность с интерфейсами, которые мы определили выше:
@GroupSequence({BasicInfo.class, AdvanceInfo.class}) public interface CompleteInfo { }
4.3. Последовательность групп тестирования
Теперь давайте проверим Последовательность групп. Во-первых, мы проверим, что если Базовая информация является неполной, то ограничение Advance Into group не будет оценено:
@Test public void whenBasicInfoIsNotComplete_thenShouldGiveConstraintViolationsForBasicInfoOnly() { RegistrationForm form = buildRegistrationFormWithBasicInfo(); form.setFirstName(""); Set> violations = validator.validate(form, CompleteInfo.class); assertThat(violations.size()).isEqualTo(1); violations.forEach(action -> { assertThat(action.getMessage()).isEqualTo("must not be blank"); assertThat(action.getPropertyPath().toString()).isEqualTo("firstName"); }); }
Теперь давайте проверим Последовательность групп. Во-первых, мы проверим, что если Базовая информация является неполной, то ограничение
@Test public void whenBasicAndAdvanceInfoIsComplete_thenShouldNotGiveConstraintViolationsWithCompleteInfoValidationGroup() { RegistrationForm form = buildRegistrationFormWithBasicAndAdvanceInfo(); Set> violations = validator.validate(form, CompleteInfo.class); assertThat(violations.size()).isEqualTo(0); }
5. Заключение
В этом кратком руководстве мы рассмотрели, как группировать ограничения javax.validation .
Как обычно, все фрагменты кода доступны на GitHub .