Spring - перенаправление после POST (даже с ошибками проверки) - PullRequest
60 голосов
/ 30 марта 2010

Я пытаюсь выяснить, как «сохранить» BindingResult, чтобы его можно было использовать в последующем GET с помощью тега Spring <form:errors>. Я хочу сделать это из-за ограничений SSL в Google App Engine. У меня есть форма, которая отображается через HTTP, и сообщение на HTTPS URL. Если бы я только перенаправлял, а не перенаправлял, то пользователь видел бы URL https://whatever.appspot.com/my/form. Я пытаюсь избежать этого. Есть идеи как к этому подойти?

Ниже я хотел бы сделать следующее, но я вижу ошибки проверки только при использовании return "create".

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(
    @ModelAttribute("register") @Valid final Register register,
    final BindingResult binding) {

    if (binding.hasErrors()) {
        return "redirect:/register/create";
    }

    return "redirect:/register/success";
}

Ответы [ 7 ]

68 голосов
/ 07 апреля 2012

С весны 3.1 вы можете использовать RedirectAttributes. Добавьте атрибуты, которые вы хотите иметь доступными перед выполнением перенаправления. Добавьте как BindingResult, так и объект, который вы используете для проверки, в этом случае Register.

Для BindingResult вы будете использовать имя: "org.springframework.validation.BindingResult. [Имя вашего ModelAttribute]".

Для объекта, который вы используете для проверки, вы будете использовать имя ModelAttribute.

Чтобы использовать атрибуты Redirect, вы должны добавить это в свой конфигурационный файл. Среди прочего вы говорите Spring использовать несколько новых классов:

<mvc:annotation-driven />

Теперь ошибки будут отображаться везде, куда вы перенаправляете

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) {

if (binding.hasErrors()) {
    attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding);
    attr.addFlashAttribute("register", register);
    return "redirect:/register/create";
}

return "redirect:/register/success";
}
55 голосов
/ 20 мая 2014

В дополнение к хорошему ответу Оскара, если вы следуете этому подходу RedirectAttributes, не забывайте, что вы фактически передаете modelAttribute на перенаправленную страницу. Это означает, что если вы создадите новый экземпляр этого атрибута модели для перенаправленной страницы (в контроллере), вы потеряете ошибки проверки . Итак, если ваш POST метод контроллера выглядит примерно так:

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(@ModelAttribute("register") @Valid final Register register, final BindingResult binding, RedirectAttributes attr, HttpSession session) {

if (binding.hasErrors()) {
    attr.addFlashAttribute("org.springframework.validation.BindingResult.register", binding);
    attr.addFlashAttribute("register", register);
    return "redirect:/register/create";
}

return "redirect:/register/success";
}

Тогда вам, вероятно, потребуется внести изменения в свой контроллер создания страницы GET контроллер. Из этого:

@RequestMapping(value = "/register/create", method = RequestMethod.GET)
public String registerCreatePage(Model model) {
    // some stuff
    model.addAttribute("register", new Register());
    // some more stuff
}

до

@RequestMapping(value = "/register/create", method = RequestMethod.GET)
public String registerCreatePage(Model model) {
    // some stuff
    if (!model.containsAttribute("register")) {
        model.addAttribute("register", new Register());
    }
    // some more stuff
}

Источник: http://gerrydevstory.com/2013/07/11/preserving-validation-error-messages-on-spring-mvc-form-post-redirect-get/

1 голос
/ 10 августа 2011

Я бы спросил, зачем вам нужен редирект. Почему бы просто не отправлять по одному и тому же URL и по-разному отвечать на POST? Тем не менее, если вы действительно хотите сделать это:

@RequestMapping(value = "/submit", method = RequestMethod.POST)
public final String submit(
    @ModelAttribute("register") @Valid final Register register,
    final BindingResult binding,
    HttpSession session) {

    if (binding.hasErrors()) {
        session.setAttribute("register",register);
        session.setAttribute("binding",binding);
        return "redirect:/register/create";
    }

    return "redirect:/register/success";
}

Тогда в вашем методе создания:

model.put("register",session.getAttribute("register"));
model.put("org.springframework.validation.BindingResult.register",session.getAttribute("register"));
1 голос
/ 03 июля 2010

Единственный способ сохранить объекты между запросами (т.е. перенаправление) - сохранить объект в атрибуте сеанса. Таким образом, вы должны включить «запрос HttpServletRequest» в параметры метода для обоих методов (т. Е. Получить и опубликовать) и получить объект через request.getAttribute («привязка»). Тем не менее, и не попробовав это самостоятельно, вам может понадобиться выяснить, как повторно привязать привязку к объекту в новом запросе.

Еще один «нехороший» способ - просто изменить URL браузера, используя javascript

1 голос
/ 10 мая 2010

Проблема в том, что вы перенаправляете на новый контроллер, а не визуализируете представление и возвращаете обработанную страницу формы. Вам нужно сделать что-то вроде:

String FORM_VIEW = wherever_your_form_page_resides

...

if (binding.hasErrors())
    return FORM_VIEW;

Я бы оставил пути вне любых методов из-за дублирования строк кода.

0 голосов
/ 04 января 2017

Я не знаю точной проблемы с Google App Engine, но использование ForwardedHeaderFilter может помочь сохранить оригинальную схему, которую использовал клиент. Этот фильтр был добавлен в Spring Framework 4.3, но некоторые контейнеры сервлетов предоставляют аналогичные фильтры, и этот фильтр самодостаточен, поэтому вы также можете просто получить источник, если это необходимо.

0 голосов
/ 21 апреля 2010

Возможно, это немного упрощенно, но вы пытались добавить его в свою модель? То есть, включите модель в аргументы вашего метода, затем добавьте в нее BindingResult, который затем станет доступен в вашем представлении.

model.addAttribute("binding",binding);

Я думаю, что вам, возможно, придется использовать переадресацию, а не перенаправление (в своей голове я не могу вспомнить, теряет ли перенаправление сеанс или нет - я могу ошибаться, так как у меня нет документации под рукой то есть, если вы не получаете BindingResult после добавления его в модель, попробуйте вместо этого использовать форвард, чтобы подтвердить это).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...