Spring MVC Controller перенаправляет, используя параметры URL вместо ответа - PullRequest
38 голосов
/ 23 марта 2010

Я пытаюсь реализовать RESTful URL в моем приложении Spring MVC. Все хорошо, за исключением обработки формы заявки. Мне нужно перенаправить обратно на исходную форму или на страницу «успеха».

@Controller
@RequestMapping("/form")
public class MyController {

    @RequestMapping(method = RequestMethod.GET)
    public String setupForm() {
        // do my stuff
        return "myform";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processForm(ModelMap model) {            
        // process form data

        model.addAttribute("notification", "Successfully did it!");
        return "redirect:/form";
    }
}

Однако, как я прочитал в Spring документации , если вы перенаправите какие-либо параметры, они будут помещены в URL. И это не работает для меня. Что было бы самым изящным способом обойти это?

Ответы [ 7 ]

34 голосов
/ 06 января 2011

У меня была такая же проблема. решил это так:

return new ModelAndView("redirect:/user/list?success=true");

И тогда мой метод контроллера выглядит следующим образом:

public ModelMap list(@RequestParam(required=false) boolean success) {
    ModelMap mm = new ModelMap();
    mm.put(SEARCH_MODEL_KEY, campaignService.listAllCampaigns());
    if(success)
        mm.put("successMessageKey", "campaign.form.msg.success");
    return mm;
}

Прекрасно работает, если вы не хотите отправлять простые данные, а не коллекции, скажем. Тогда тебе придется использовать сессию, я думаю.

10 голосов
/ 12 марта 2013

Эта проблема вызвана (как утверждали другие) тем, что атрибуты модели сохраняются в строке запроса - это обычно нежелательно и рискует создать дыры в безопасности, а также смешные строки запроса. Мое обычное решение - никогда не использовать строки для перенаправлений в Spring MVC, вместо этого используйте RedirectView, который можно настроить так, чтобы он не отображал атрибуты модели (см .: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/view/RedirectView.html)

RedirectView(String url, boolean contextRelative, boolean http10Compatible, boolean exposeModelAttributes)

Так что, как правило, у меня есть метод util, который выполняет «безопасное перенаправление», например:

public static RedirectView safeRedirect(String url) {
    RedirectView rv = new RedirectView(url);
    rv.setExposeModelAttributes(false);
    return rv;
}

Другой вариант - использовать XML конфигурации bean:

<bean id="myBean" class="org.springframework.web.servlet.view.RedirectView">
   <property name="exposeModelAttributes" value="false" />
   <property name="url" value="/myRedirect"/>
</bean>

Опять же, вы можете абстрагировать это в свой собственный класс, чтобы избежать повторения (например, SafeRedirectView).


Примечание об «очистке модели» - это не то же самое, что «не показывать модель» при любых обстоятельствах. На одном сайте, над которым я работал, было много фильтров, которые добавляли вещи в модель, это означало, что очистка модели перед перенаправлением не помешает длинной строке запроса. Я также хотел бы предположить, что «недопущение атрибутов модели» является более семантическим подходом, чем «очистка модели перед перенаправлением».

8 голосов
/ 23 марта 2010

Вы можете сделать так, чтобы processForm() возвращал объект View, и он возвращал конкретный тип RedirectView, у которого есть параметр для setExposeModelAttributes().

Когда вы возвращаете имя представления с префиксом "redirect:", Spring MVC в любом случае преобразует его в объект RedirectView, он просто делает это с setExposeModelAttributes в true (что, я думаю, является нечетным значением по умолчанию).

7 голосов
/ 23 марта 2010

http://jira.springframework.org/browse/SPR-6464 предоставил мне то, что мне нужно, чтобы все заработало, пока Spring MVC не предложит эту функциональность (возможно, в версии 3.0.2). Хотя я просто реализовал классы, которые они временно, и добавил фильтр в контекст моего веб-приложения. Прекрасно работает!

4 голосов
/ 23 марта 2010

Если вам не нужно сообщение об успешном завершении в URL-адресе, то можно добавить его в сеанс (в методе processForm), а затем проверить его (и удалить) в методе setupForm.

Отредактировано для добавления: если это неудобно делать вручную, тогда вы можете написать подкласс RedirectView, который добавляет атрибут «message» и оборачивает процесс его вставки в сеанс. Не уверен, однако, есть ли простой способ вернуть сообщение из сеанса ...

Честно говоря, я не думаю, что есть простой ответ - природа перенаправления HTTP заключается в том, что состояние не переносится; если вы все равно хотите поддерживать состояние, вы застряли с различными обычными способами поддержания состояния в веб-приложениях: сеанс, cookie, строка запроса ...

3 голосов
/ 26 января 2016

Эй, вы можете просто сделать одну простую вещь вместо использования модели для отправки параметра, используйте объект HttpServletRequest и сделайте это

HttpServletRequest request;
request.setAttribute("param", "value")

теперь ваши параметры не будут отображаться в вашем заголовке URL, надеюсь, что это работает:)

1 голос
/ 04 сентября 2017
@RequestMapping(path="/apps/add", method=RequestMethod.POST)
public String addApps(String appUrl, Model model, final RedirectAttributes redirectAttrs) {
    if (!validate(appUrl)) {
       redirectAttrs.addFlashAttribute("error", "Validation failed");
    }
    return "redirect:/apps/add"
} 

@RequestMapping(path="/apps/add", method=RequestMethod.GET)
public String addAppss(Model model) {
    String error = model.asMap().get("error");
}
...