Статьи

Группы проверки в Spring MVC

Логотип-весна-ю

Ограничения проверки в Bean Validation могут быть добавлены к одной или нескольким группам через атрибут groups . Это позволяет вам ограничить набор ограничений, применяемых во время проверки. Это может быть полезно в тех случаях, когда некоторые группы должны быть проверены раньше других, например, в мастерах. Начиная с Spring MVC 3.1, автоматическая проверка с использованием групп проверки возможна с помощью org.springframework.validation.annotation.Validated annotation. В этой статье я буду использовать простое приложение Spring MVC, чтобы продемонстрировать, насколько легко вы можете использовать группы проверки для проверки атрибутов модели Spring MVC.

форма

Давайте начнем с класса формы, который будет проверяться поэтапно. Во-первых, мы определяем интерфейсы, которые представляют группы ограничений:

01
02
03
04
05
06
07
08
09
10
public class Account implements PasswordAware {
 
    interface ValidationStepOne {
        // validation group marker interface
    }
 
    interface ValidationStepTwo {
        // validation group marker interface
    }
}

Валидационные ограничения

Далее мы назначаем ограничения для групп. Помните, что если вы не предоставите группы, будет использоваться группа по умолчанию. Также обратите внимание на @SamePasswords , @StrongPassword — пользовательские ограничения, которые должны определять атрибут groups :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@SamePasswords(groups = {Account.ValidationStepTwo.class})
public class Account implements PasswordAware {
 
    @NotBlank(groups = {ValidationStepOne.class})
    private String username;
 
    @Email(groups = {ValidationStepOne.class})
    @NotBlank(groups = {ValidationStepOne.class})
    private String email;
 
    @NotBlank(groups = {ValidationStepTwo.class})
    @StrongPassword(groups = {ValidationStepTwo.class})
    private String password;
 
    @NotBlank(groups = {ValidationStepTwo.class})
    private String confirmedPassword;
 
    // getters and setters
}

колдун

Имея Account , мы можем создать @Controller мастер @Controller , который позволит пользователям создавать учетные записи. На первом этапе мы позволим Spring проверить ограничение в группе ValidationStepOne :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@Controller
@RequestMapping("validationgroups")
@SessionAttributes("account")
public class AccountController {
 
    @RequestMapping(value = "stepOne")
    public String stepOne(Model model) {
        model.addAttribute("account", new Account());
        return VIEW_STEP_ONE;
    }
 
    @RequestMapping(value = "stepOne", method = RequestMethod.POST)
    public String stepOne(@Validated(Account.ValidationStepOne.class) Account account, Errors errors) {
        if (errors.hasErrors()) {
            return VIEW_STEP_ONE;
        }
        return "redirect:stepTwo";
    }
}

Для запуска проверки с группами я использовал аннотацию @Validated . Эта аннотация принимает аргумент var-arg с типами групп. Код @Validated(ValidationStepOne.class) запускает проверку ограничения в группе ValidationStepOne .

На следующем шаге мы позволим Spring проверить ограничение в группе ValidationStepTwo :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
@Controller
@RequestMapping("validationgroups")
@SessionAttributes("account")
public class AccountController {
 
    @RequestMapping(value = "stepTwo")
    public String stepTwo() {
        return VIEW_STEP_TWO;
    }
 
    @RequestMapping(value = "stepTwo", method = RequestMethod.POST)
    public String stepTwo(@Validated(Account.ValidationStepTwo.class) Account account, Errors errors) {
        if (errors.hasErrors()) {
            return VIEW_STEP_TWO;
        }
        return "redirect:summary";
    }
}

На итоговом этапе мы подтвердим введенные данные и позволим Spring проверить ограничение обеих групп:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
@Controller
@RequestMapping("validationgroups")
@SessionAttributes("account")
public class AccountController {
 
    @RequestMapping(value = "summary")
    public String summary() {
        return VIEW_SUMMARY;
    }
 
    @RequestMapping(value = "confirm")
    public String confirm(@Validated({Account.ValidationStepOne.class, Account.ValidationStepTwo.class}) Account account, Errors errors, SessionStatus status) {
        status.setComplete();
        if (errors.hasErrors()) {
            // did not pass full validation
        }
        return "redirect:start";
    }
}

До весны 3.1 вы могли запустить проверку вручную. Я описал это в одном из моих предыдущих постов: http://blog.codeleak.pl/2011/03/how-to-jsr303-validation-groups-in.html

Примечание. Если вы хотите использовать группы проверки без Spring, вам нужно передать группы в javax.validation.Validator#validate() :

Валидация групп без Spring

01
02
03
04
05
06
07
08
09
10
11
12
13
Validator validator = Validation
        .buildDefaultValidatorFactory().getValidator();
Account account = new Account();
 
// validate with first group
Set<ConstraintViolation<Account>> constraintViolations =
        validator.validate(account, Account.ValidationStepOne.class);
assertThat(constraintViolations).hasSize(2);
 
// validate with both groups
Set<ConstraintViolation<Account>> constraintViolations =
        validator.validate(account, Account.ValidationStepOne.class, Account.ValidationStepTwo.class);
assertThat(constraintViolations).hasSize(4);

Это также самый простой способ проверить валидации:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class AccountValidationTest {
 
    private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
 
    @Test
    public void shouldHaveFourConstraintViolationsWhileValidatingBothGroups() {
        Account account = new Account();
        Set<ConstraintViolation<Account>> constraintViolations = validator.validate(
                account, Account.ValidationStepOne.class, Account.ValidationStepTwo.class
        );
        assertThat(constraintViolations).hasSize(4);
    }
 
    @Test
    public void shouldHaveTwoConstraintViolationsWhileStepOne() {
        Account account = new Account();
        Set<ConstraintViolation<Account>> constraintViolations = validator.validate(
                account, Account.ValidationStepOne.class
        );
        assertThat(constraintViolations).hasSize(2);
 
    }
}

Проверка правильности с помощью Spring Test

Проверка проверки с помощью Spring Test предлагает более сложный способ проверки, если проверка / привязка не удалась. Для примеров, посмотрите на мое другое сообщение в блоге: Spring MVC Integration Testing: Утвердите, что у данных атрибутов модели есть глобальные ошибки