Java Spring - POST 后重定向(即使有验证错误)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2543797/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring - Redirect after POST (even with validation errors)
提问by Taylor Leese
I'm trying to figure out how to "preserve" the BindingResult so it can be used in a subsequent GET via the Spring <form:errors>
tag. The reason I want to do this is because of Google App Engine's SSL limitations. I have a form which is displayed via HTTP and the post is to an HTTPS URL. If I only forward rather than redirect then the user would see the https://whatever.appspot.com/my/formURL. I'm trying to avoid this. Any ideas how to approach this?
我试图弄清楚如何“保留” BindingResult 以便它可以通过 Spring<form:errors>
标签在后续的 GET 中使用。我想这样做的原因是因为 Google App Engine 的 SSL 限制。我有一个通过 HTTP 显示的表单,帖子是一个 HTTPS URL。如果我只转发而不是重定向,那么用户将看到https://whatever.appspot.com/my/formURL。我正在努力避免这种情况。任何想法如何解决这个问题?
Below is what I'd like to do, but I only see validation errors when I use return "create"
.
下面是我想要做的,但是当我使用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";
}
回答by Ichiro Furusato
Perhaps this is a bit simplistic, but have you tried adding it to your Model? I.e., include the Model in your method's arguments, then add the BindingResult to it, which is then available in your view.
也许这有点简单,但是您是否尝试将其添加到您的模型中?即,将模型包含在方法的参数中,然后将 BindingResult 添加到它,然后在您的视图中可用。
model.addAttribute("binding",binding);
I think you may have to use a forward rather than a redirect (in my head I can't remember if a redirect loses the session or not — I could be wrong about this as I don't have any documentation handy, i.e., if you're not getting the BindingResult after adding it to the Model, try using a forward instead to confirm this).
我认为您可能必须使用转发而不是重定向(在我的脑海中,我不记得重定向是否会丢失会话 - 我可能是错误的,因为我手头没有任何文档,即,如果将其添加到模型后,您没有获得 BindingResult,请尝试使用转发来确认这一点)。
回答by Lewis
The problem is you're redirecting to a new controller, rather than rendering the view and returning the processed form page. You need to do something along the lines of:
问题是您正在重定向到一个新的控制器,而不是呈现视图并返回已处理的表单页面。您需要按照以下方式做一些事情:
String FORM_VIEW = wherever_your_form_page_resides
...
if (binding.hasErrors())
return FORM_VIEW;
I would keep the paths outside of any methods due to code duplication of strings.
由于字符串的代码重复,我会将路径保留在任何方法之外。
回答by klonq
The only way to persist objects between requests (ie a redirect) is to store the object in a session attribute. So you would include "HttpServletRequest request" in method parameters for both methods (ie, get and post) and retrieve the object via request.getAttribute("binding"). That said, and having not tried it myself you may need to figure out how to re-bind the binding to the object in the new request.
在请求之间持久化对象的唯一方法(即重定向)是将对象存储在会话属性中。因此,您将在两种方法(即 get 和 post)的方法参数中包含“HttpServletRequest request”,并通过 request.getAttribute("binding") 检索对象。也就是说,如果自己没有尝试过,您可能需要弄清楚如何将绑定重新绑定到新请求中的对象。
Another "un-nicer" way is to just change the browser URL using javascript
另一种“不太好”的方法是使用 javascript 更改浏览器 URL
回答by rjsang
I would question why you need the redirect. Why not just submit to the same URL and have it respond differently to a POST? Nevertheless, if you really want to do this:
我会质疑你为什么需要重定向。为什么不直接提交到相同的 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";
}
Then in your "create" method:
然后在您的“创建”方法中:
model.put("register",session.getAttribute("register"));
model.put("org.springframework.validation.BindingResult.register",session.getAttribute("register"));
回答by Oscar
Since Spring 3.1 you can use RedirectAttributes. Add the attributes that you want to have available before doing the redirect. Add both, the BindingResult and the object that you are using to validate, in this case Register.
从 Spring 3.1 开始,您可以使用 RedirectAttributes。在执行重定向之前添加您希望可用的属性。添加 BindingResult 和用于验证的对象,在本例中为 Register。
For BindingResult you will use the name: "org.springframework.validation.BindingResult.[name of your ModelAttribute]".
对于 BindingResult,您将使用名称:“org.springframework.validation.BindingResult.[您的 ModelAttribute 名称]”。
For the object that you are using to validate you will use the name of ModelAttribute.
对于用于验证的对象,您将使用 ModelAttribute 的名称。
To use RedirectAttributes you have to add this in your config file. Among other things you are telling to Spring to use some newer classes:
要使用 RedirectAttributes,您必须在配置文件中添加它。除其他事项外,您还告诉 Spring 使用一些较新的类:
<mvc:annotation-driven />
Now the errors will be displayed wherever you are redirecting
现在错误将显示在您重定向的任何地方
@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";
}
回答by Utku ?zdemir
In addition to Oscar's nice answer, if you are following that RedirectAttributes
approach, do not forget that you are actually passing the modelAttribute
to the redirected page. This means if you create a new instance of that modelAttribute for the redirected page (in a controller), you will lose the validation errors. So, if your POSTcontroller method is something like this:
除了奥斯卡的好答案,如果您遵循这种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";
}
Then you will probably need to do a modification in your register create page GETcontroller. From this:
然后您可能需要在注册创建页面GET控制器中进行修改。由此:
@RequestMapping(value = "/register/create", method = RequestMethod.GET)
public String registerCreatePage(Model model) {
// some stuff
model.addAttribute("register", new Register());
// some more stuff
}
to
到
@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/
回答by Rossen Stoyanchev
I don't know the exact issue with Google App Engine but using the ForwardedHeaderFiltermay help to preserve the original scheme that the client used. This filter was added in Spring Framework 4.3 but some Servlet containers provide similar filters and the filter is self-sufficient so you can also just grab the source if needed.
我不知道 Google App Engine 的确切问题,但使用ForwardedHeaderFilter可能有助于保留客户端使用的原始方案。这个过滤器是在 Spring Framework 4.3 中添加的,但一些 Servlet 容器提供了类似的过滤器,并且过滤器是自给自足的,所以你也可以根据需要获取源代码。