Spring-POST 后重定向(即使有验证错误)

我试图找出如何“保存”BindingResult,以便通过 Spring<form:errors>标记在后续 GET 中使用它。我想这样做的原因是因为 GoogleAppEngine 的 SSL 限制。我有一个通过 HTTP 显示的表单,这个帖子是一个 HTTPS URL。如果我只转发而不是重定向,那么用户将看到 https://whatever.appspot.com/my/form URL。我尽量避免这样。有什么办法吗?

下面是我想要做的,但是我只在使用 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";
}
83431 次浏览

也许这有点过于简单,但是您尝试过将它添加到您的 Model 中吗?例如,将 Model 包含在方法的参数中,然后将 BindingResult 添加到其中,这将在视图中可用。

model.addAttribute("binding",binding);

我认为你可能不得不使用转发而不是重定向(在我的脑海中,我不记得重定向是否会丢失会话或不 & mash; 我可能是错误的,因为我手边没有任何文档,也就是说,如果你没有得到 BindingResult 后,将其添加到模型,尝试使用转发来确认这一点)。

问题是您正在重定向到一个新的控制器,而不是呈现视图并返回处理过的表单页面。你需要做的事情大致如下:

String FORM_VIEW = wherever_your_form_page_resides


...


if (binding.hasErrors())
return FORM_VIEW;

由于字符串的代码复制,我会将路径保留在任何方法之外。

在请求之间(即重定向)持久化对象的唯一方法是将对象存储在会话属性中。因此,可以在两个方法(即 get 和 post)的方法参数中包含“ HttpServletRequest”,并通过 request.getAttribute (“ bind”)检索对象。也就是说,在没有亲自尝试过之前,您可能需要弄清楚如何在新请求中将绑定重新绑定到对象。

另一种“不好的”方法是使用 javascript 更改浏览器 URL

我会质疑你为什么需要重定向。为什么不直接提交到同一个 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"));

从 Spring 3.1开始,您可以使用 RedirectAttritribute。在执行重定向之前添加希望具有的属性。同时添加 BindingResult 和您用于验证的对象(在本例中为 Register)。

对于 BindingResult,您将使用名称: “ org.springframework.valid.BindingResult. [ name of your ModelAttribute ]”。

对于您用来验证的对象,您将使用 ModelAttribute 的名称。

要使用重定向属性,必须在配置文件中添加此属性。除此之外,你还告诉 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";
}

除了 Oscar 的漂亮回答之外,如果您遵循 RedirectAttributes方法,不要忘记您实际上是将 modelAttribute传递给重定向页面。这意味着,如果您为重定向页面(在控制器中)创建了一个 model Attribute 的新实例,您将丢失验证错误。因此,如果您的 职位控制器方法类似于下面这样:

@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";
}

然后,您可能需要在您的寄存器中做一个修改,创建页面 走开控制器:

@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/

我不知道谷歌应用程序引擎的确切问题,但使用 转发头过滤器可能有助于保存客户端使用的原始方案。这个过滤器是在 Spring Framework 4.3中添加的,但是一些 Servlet 容器提供了类似的过滤器,而且这个过滤器是自给自足的,所以如果需要的话,您也可以直接获取源代码。