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

mlnl4t2r  于 2022-10-30  发布在  Spring
关注(0)|答案(7)|浏览(205)

我正在尝试弄清楚如何“保留”BindingResult,以便它可以通过Spring <form:errors>标记在后续GET中使用。我想这样做的原因是因为Google App Engine的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";
}
nbysray5

nbysray51#

从Spring 3.1开始,您可以使用RedirectAttributes。在执行重定向之前添加您希望可用的属性。添加BindingResult和您用于验证的对象,在本例中为Register。
对于BindingResult,您将使用以下名称:“[模型属性的名称]"。
对于用于验证的对象,将使用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";
}
ukxgm1gy

ukxgm1gy2#

除了Oscar的回答之外,如果你使用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
}

来源:http://gerrydevstory.com/2013/07/11/preserving-validation-error-messages-on-spring-mvc-form-post-redirect-get/

ki1q1bka

ki1q1bka3#

我会问你为什么需要重定向。为什么不直接提交到同一个URL,让它对一个帖子做出不同的响应呢?尽管如此,如果你真的想这样做:

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

然后在你的“create”方法中:

model.put("register",session.getAttribute("register"));
model.put("org.springframework.validation.BindingResult.register",session.getAttribute("register"));
vwhgwdsa

vwhgwdsa4#

问题是您要重定向到一个新的控制器,而不是呈现视图并返回处理过的表单页面。

String FORM_VIEW = wherever_your_form_page_resides

...

if (binding.hasErrors())
    return FORM_VIEW;

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

rqenqsqc

rqenqsqc5#

在请求(即重定向)之间持久化对象的唯一方法是将对象存储在会话属性中。因此,您可以在两个方法(即get和post)的方法参数中包含“HttpServletRequest request”,并通过request.getAttribute(“binding”)检索对象。也就是说,如果您自己没有尝试过,可能需要弄清楚如何在新请求中将绑定重新绑定到对象。
另一种“不太好”的方法是使用javascript更改浏览器URL

cyej8jka

cyej8jka6#

我不知道Google App Engine的确切问题,但使用ForwardedHeaderFilter可能有助于保留客户端使用的原始方案。这个过滤器是在Spring Framework 4.3中添加的,但一些Servlet容器提供类似的过滤器,而且过滤器是自给自足的,因此如果需要,您也可以只获取源代码。

balp4ylt

balp4ylt7#

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

model.addAttribute("binding",binding);

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

相关问题