Spring MVC @Validation с интерфейсом маркера в методе общего контроллера

У меня есть приложение для опросов Spring MVC, где метод Controller, вызываемый каждой формой POST, практически идентичен:

@PostMapping("/1")
public String processGroupOne (
        Model model,
        @ModelAttribute("pageNum") int pageNum, 
        @ModelAttribute(GlobalControllerAdvice.SESSION_ATTRIBUTE_NAME) @Validated(SurveyGroupOne.class) SurveyCommand surveyCommand, 
        BindingResult result) {
    if (result.hasErrors()) {
        LOG.debug(result.getAllErrors().toString());
        model.addAttribute("pageNum", pageNum);
        return "survey/page".concat(Integer.toString(pageNum));
    }
    pageNum++;
    model.addAttribute("pageNum", pageNum);
    return "redirect:/survey/".concat(Integer.toString(pageNum));
}

Единственное отличие состоит в том, какая часть объекта SurveyCommand проверяется на каждой остановке по пути. Это обозначается интерфейсом маркера, переданным аннотации @Validated(). Интерфейсы маркеров (SurveyGroupOne, SurveyGroupTwo и т. Д.) - это всего лишь маркеры:

public interface SurveyGroupOne {}
public interface SurveyGroupTwo {}
...

и они применяются к свойствам объектов в объекте SurveyCommand:

public class Person {
    @NotBlank(groups = {
                    SurveyGroupTwo.class, 
                    SurveyGroupThree.class})
    private String firstName;
    @NotBlank(groups = {
                    SurveyGroupTwo.class, 
                    SurveyGroupThree.class})
    private String lastName;
...
}

Мой вопрос: как я могу сделать метод универсальным и при этом использовать интерфейс маркера, специфичный для обрабатываемой страницы? Что-то вроде этого:

@PostMapping("/{pageNum}")
public String processGroupOne (
        Model model,
        @PathVariable("pageNum") int pageNum, 
        @ModelAttribute(GlobalControllerAdvice.SESSION_ATTRIBUTE_NAME) 
            @Validated(__what goes here??__) SurveyCommand surveyCommand, 
        BindingResult result) {
    if (result.hasErrors()) {
        LOG.debug(result.getAllErrors().toString());
        model.addAttribute("pageNum", pageNum);
        return "survey/page".concat(Integer.toString(pageNum));
    }
    pageNum++;
    model.addAttribute("pageNum", pageNum);
    return "redirect:/survey/".concat(Integer.toString(pageNum));
}

Как я могу передать правильный интерфейс маркера в @Validated исключительно на основе pageNum @PathVariable (или любого другого параметра)?

1 ответ

Так как @Validated это аннотация, она требует, чтобы ее аргументы были доступны во время компиляции и, следовательно, были статическими. Вы все еще можете использовать его, но в этом случае у вас будет N методов, где N - это количество шагов. Чтобы отличить один шаг от другого вы можете использовать params аргумент @PostMapping аннотация.

Существует также другой способ, где вам нужно вводить Validator к контроллеру и вызовите его напрямую с соответствующей группой, которая вам нужна.

Другие вопросы по тегам