我正在试图找出如何“保留”BindingResult,以便可以通过Spring <form:errors>
标记在后续GET中使用它。我想这样做的原因是因为Google App Engine的SSL限制。我有一个通过HTTP显示的表单,帖子是一个HTTPS 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";
}
答案 0 :(得分:68)
从Spring 3.1开始,您可以使用RedirectAttributes。在执行重定向之前添加要提供的属性。添加BindingResult和您用于验证的对象,在本例中为Register。
对于BindingResult,您将使用名称:“org.springframework.validation.BindingResult。[ModelAttribute的名称]”。
对于您用于验证的对象,您将使用ModelAttribute的名称。
要使用RedirectAttributes,您必须在配置文件中添加它。您告诉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";
}
答案 1 :(得分:54)
除了奥斯卡的好答案之外,如果您遵循RedirectAttributes
方法,请不要忘记您实际上已将modelAttribute
传递到重定向的页面。这意味着如果为重定向页面(在控制器中)创建该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
}
答案 2 :(得分:1)
问题是您是重定向到新控制器,而不是渲染视图并返回已处理的表单页面。你需要做一些事情:
String FORM_VIEW = wherever_your_form_page_resides
...
if (binding.hasErrors())
return FORM_VIEW;
由于代码重复字符串,我会将路径保留在任何方法之外。
答案 3 :(得分:1)
在请求之间保持对象(即重定向)的唯一方法是将对象存储在会话属性中。因此,您将在两个方法(即get和post)的方法参数中包含“HttpServletRequest request”,并通过request.getAttribute(“binding”)检索对象。也就是说,并且自己没有尝试过,您可能需要弄清楚如何在新请求中将绑定重新绑定到对象。
另一种“不太好”的方法是只使用javascript更改浏览器URL
答案 4 :(得分:1)
我会问你为什么需要重定向。为什么不提交到相同的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"));
答案 5 :(得分:0)
我不知道Google App Engine的确切问题,但使用ForwardedHeaderFilter可能有助于保留客户端使用的原始方案。这个过滤器是在Spring Framework 4.3中添加的,但是一些Servlet容器提供了类似的过滤器,并且过滤器是自给自足的,所以你也可以在需要时获取源代码。
答案 6 :(得分:-1)
也许这有点过分了,但您是否尝试将其添加到模型中?即,在方法的参数中包含Model,然后将BindingResult添加到它,然后在视图中可用。
model.addAttribute("binding",binding);
我认为你可能不得不使用前向而不是重定向(在我脑海中,我不记得重定向是否会丢失会话 - 我可能错了,因为我没有任何文档方便,即,如果你在将BindingResult添加到模型后没有得到BindingResult,请尝试使用forward来确认这一点。