Spring Контроллер MVC перенаправляет параметры URL вместо ответа
Я пытаюсь внедрить URL-адреса RESTful в моем приложении 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-адрес. И это не работает для меня. Каким будет самый изящный способ этого?
Ответы
Ответ 1
http://jira.springframework.org/browse/SPR-6464 предоставил мне то, что мне нужно, чтобы все работало до тех пор, пока Spring MVC не предложит функциональность (возможно, в 3.0.2 выпуск). Хотя я просто реализовал классы, которые они временно использовали, и добавил фильтр в мой контекст веб-приложения. Отлично работает!
Ответ 2
У меня была та же проблема. решил это следующим образом:
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;
}
Работает отлично, если вы не хотите отправлять простые данные, а не коллекции. Тогда вам придется использовать сеанс, я думаю.
Ответ 3
Эта проблема вызвана (как утверждали другие) атрибуты модели, которые сохраняются в строке запроса - это обычно нежелательно и может создавать уязвимости безопасности, а также смешные строки запросов. Мое обычное решение - никогда не использовать Strings для перенаправления в 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)
Итак, я имею тенденцию использовать метод утилиты, который выполняет "безопасное перенаправление":
public static RedirectView safeRedirect(String url) {
RedirectView rv = new RedirectView(url);
rv.setExposeModelAttributes(false);
return rv;
}
Другой вариант - использовать bean конфигурацию XML:
<bean id="myBean" class="org.springframework.web.servlet.view.RedirectView">
<property name="exposeModelAttributes" value="false" />
<property name="url" value="/myRedirect"/>
</bean>
Опять же, вы можете абстрагировать это в свой класс, чтобы избежать повторения (например, SafeRedirectView).
Заметка об "очищении модели" - это не то же самое, что "не подвергать модель" при любых обстоятельствах. На одном сайте, на котором я работал, было много фильтров, которые добавили вещи в модель, это означало, что очистка модели до перенаправления не помешала бы длинной строке запроса. Я бы также предположил, что "не подвергать атрибутам модели" более семантический подход, чем "очистка модели перед перенаправлением".
Ответ 4
Вместо processForm()
можно вернуть объект View и вернуть ему конкретный тип RedirectView
, у которого есть параметр для setExposeModelAttributes()
.
Когда вы возвращаете имя представления с префиксом "redirect:"
, Spring MVC превращает это в объект RedirectView
в любом случае, он просто делает это с setExposeModelAttributes
в true (что, по моему мнению, является нечетным значением по умолчанию,).
Ответ 5
Если вам не требуется сообщение об успешности в URL-адресе, тогда один параметр должен поместить его в сеанс (в методе processForm), а затем проверить его (и удалить) в методе setupForm.
Отредактировано для добавления: если это больно делать вручную, вы можете написать подкласс RedirectView, который добавляет атрибут "сообщение" и переносит процесс вставки его в сеанс. Не уверен, однако, если есть простой способ обернуть вывод сообщения из сеанса...
Честно говоря, я не думаю, что есть простой ответ - природа перенаправления HTTP заключается в том, что состояние не переносится; если вы хотите сохранить состояние в любом случае, вы застряли с различными обычными способами поддержания состояния в веб-приложениях: сеанс, куки файл, запрос...
Ответ 6
Эй, вы можете просто сделать одну простую вещь вместо того, чтобы использовать модель для отправки параметра, использовать объект HttpServletRequest и сделать это
HttpServletRequest request;
request.setAttribute("param", "value")
теперь ваши параметры не будут отображаться в заголовке вашего URL-адреса, надеюсь, что он работает:)
Ответ 7
@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");
}