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

我试图弄清楚如何“保留” BindingResult,以便可以通过Spring return "create"标签在后续的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";
}
7个解决方案
67 votes

从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";
}
Oscar answered 2019-10-09T12:10:19Z
54 votes

除了奥斯卡的好答案之外,如果您遵循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/]

Utku Özdemir answered 2019-10-09T12:11:03Z
1 votes

问题是您要重定向到新的控制器,而不是呈现视图并返回已处理的表单页面。 您需要执行以下操作:

String FORM_VIEW = wherever_your_form_page_resides

...

if (binding.hasErrors())
    return FORM_VIEW;

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

Lewis answered 2019-10-09T12:11:35Z
1 votes

在请求之间保留对象的唯一方法(即重定向)是将对象存储在会话属性中。 因此,您将在两个方法的方法参数中都包含“ HttpServletRequest请求”(即get和post),并通过request.getAttribute(“ binding”)检索对象。 话虽如此,并且您自己还没有尝试过,您可能需要弄清楚如何在新请求中将绑定重新绑定到对象。

另一种“更简单”的方法是仅使用javascript更改浏览器URL

klonq answered 2019-10-09T12:12:14Z
1 votes

我会问你为什么需要重定向。 为什么不只是提交到相同的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"));
rjsang answered 2019-10-09T12:12:47Z
0 votes

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

Rossen Stoyanchev answered 2019-10-09T12:13:14Z
-1 votes

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

model.addAttribute("binding",binding);

我认为您可能必须使用转发而不是重定向(在我的脑海中,我不记得重定向是否丢失了会话-我对此可能是错误的,因为我没有任何方便的文档,即 您将BindingResult添加到模型后没有得到,请尝试使用Forward来确认)。

Ichiro Furusato answered 2019-10-09T12:13:48Z
translate from https://stackoverflow.com:/questions/2543797/spring-redirect-after-post-even-with-validation-errors