代码之家  ›  专栏  ›  技术社区  ›  Taylor Leese

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

  •  57
  • Taylor Leese  · 技术社区  · 14 年前

    我正试图找出如何“保留”BindingResult,以便它可以在通过Spring的后续GET中使用 <form:errors> 标签。我之所以这么做是因为Google App Engine的SSL限制。我有一个表单,它是通过HTTP显示的,post是一个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";
    }
    
    7 回复  |  直到 14 年前
        1
  •  70
  •   Oscar    12 年前

    自Spring3.1以来,您可以使用RedirectAttributes。在执行重定向之前,添加要使用的属性。在本例中,添加BindingResult和用于验证的对象。

    对于BindingResult,您将使用名称:“org.springframework.validation.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";
    }
    
        2
  •  58
  •   Utku Özdemir    10 年前

    除了奥斯卡漂亮的回答,如果你在听 RedirectAttributes 靠近,别忘了你实际上是在通过 modelAttribute 转到重定向页面。这意味着如果为重定向页面(在控制器中)创建该modelAttribute的新实例, 您将丢失验证错误 . 所以,如果你 岗位 控制器方法如下:

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

    那么您可能需要在register create页面中进行修改 得到 控制器。由此:

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

        3
  •  2
  •   rjsang    13 年前

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

    然后在“创建”方法中:

    model.put("register",session.getAttribute("register"));
    model.put("org.springframework.validation.BindingResult.register",session.getAttribute("register"));
    
        4
  •  1
  •   Lewis    14 年前

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

    String FORM_VIEW = wherever_your_form_page_resides
    
    ...
    
    if (binding.hasErrors())
        return FORM_VIEW;
    

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

        5
  •  1
  •   klonq    14 年前

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

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

        6
  •  0
  •   Rossen Stoyanchev    8 年前

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

        7
  •  -1
  •   Ichiro Furusato    14 年前

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

    model.addAttribute("binding",binding);
    

    我认为您可能需要使用转发而不是重定向(在我的脑海中,我记不起重定向是否会丢失会话—我可能对此有误,因为我手头没有任何文档,即,如果在将绑定结果添加到模型后,您没有得到绑定结果,请尝试使用转发来确认这一点)。