Forms 使用Post/Redirect/Get模式保留模型状态

Forms 使用Post/Redirect/Get模式保留模型状态,forms,spring-mvc,Forms,Spring Mvc,目前,我正试图用SpringMVC3.1实现Post/Redirect/Get模式。保存和恢复模型数据+验证错误的正确方法是什么?我知道我可以在POST方法中使用RedirectAttribute保留模型和BindingResult。但是,在从flash scope获取方法中恢复它们的正确方法是什么 我已经做了以下工作来发布: @RequestMapping(value = "/user/create", method = RequestMethod.POST) public Strin

目前,我正试图用SpringMVC3.1实现Post/Redirect/Get模式。保存和恢复模型数据+验证错误的正确方法是什么?我知道我可以在POST方法中使用RedirectAttribute保留模型和BindingResult。但是,在从flash scope获取方法中恢复它们的正确方法是什么

我已经做了以下工作来发布:

    @RequestMapping(value = "/user/create", method = RequestMethod.POST)
public String doCreate(@ModelAttribute("user") @Valid User user, BindingResult result, RedirectAttributes rA){

    if(result.hasErrors()){
        rA.addFlashAttribute("result", result);
        rA.addFlashAttribute("user", user);

        return "redirect:/user";
    }

    return "redirect:/user/success";
}
以及以下内容以获取用户创建表单:

    @RequestMapping(value = "/user", method = RequestMethod.GET)
public ModelAndView showUserForm(@ModelAttribute("user") User user, ModelAndView model){

    model.addObject("user", user);
    model.setViewName("userForm");

    return model;
}
这允许我在发生错误时保留给定的用户数据。但是恢复错误的正确方法是什么?(BindingResult)我想用spring表单标记在表单中显示它们:

<form:errors path="*" />


此外,如何从get方法访问flash作用域也很有趣?

为什么不在绑定失败后显示更新表单,以便用户可以尝试重新提交表单

这方面的标准方法似乎是从POST处理程序方法返回更新表单视图

if (bindingResult.hasErrors()) {
  uiModel.addAttribute("user", user);
  return "user/create";
}
然后可以使用form:errors标记显示错误

在GET方法中从中恢复它们的正确方法是什么 闪光镜

我不确定我是否理解你说的找回它们是什么意思。在重定向之前添加为flash属性的内容将在重定向之后的模型中。没有什么特别需要做的。我想你是想问别的问题,但我不确定那是什么

正如phahn指出的,为什么在出现错误时重定向?处理此问题的常用方法是在成功时重定向。

公共类BindingHandlerInterceptor扩展了HandlerInterceptorAdapter{
public class BindingHandlerInterceptor extends HandlerInterceptorAdapter {

    public static final String BINDING_RESULT_FLUSH_ATTRIBUTE_KEY = BindingHandlerInterceptor.class.getName() + ".flashBindingResult";

    private static final String METHOD_GET = "GET";
    private static final String METHOD_POST = "POST";


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {


        if(METHOD_POST.equals(request.getMethod())) {

            BindingResult bindingResult = getBindingResult(modelAndView);

            FlashMap outFlash = RequestContextUtils.getOutputFlashMap(request);

            if(bindingResult == null || ! bindingResult.hasErrors() || outFlash == null ) {
                return;
            }

            outFlash.put(BINDING_RESULT_FLUSH_ATTRIBUTE_KEY, bindingResult);

        }

        Map<String, ?> inFlash = RequestContextUtils.getInputFlashMap(request);

        if(METHOD_GET.equals(request.getMethod()) && inFlash != null && inFlash.containsKey(BINDING_RESULT_FLUSH_ATTRIBUTE_KEY)) {

            BindingResult flashBindingResult = (BindingResult)inFlash.get(BINDING_RESULT_FLUSH_ATTRIBUTE_KEY);

            if(flashBindingResult != null) {

                BindingResult bindingResult = getBindingResult(modelAndView);

                if(bindingResult == null) {
                    return;
                }

                bindingResult.addAllErrors(flashBindingResult);

            }

        }

    }

    public static BindingResult getBindingResult(ModelAndView modelAndView) {

        if(modelAndView == null) {
            return null;
        }

        for (Entry<String,?> key : modelAndView.getModel().entrySet()) {
            if(key.getKey().startsWith(BindingResult.MODEL_KEY_PREFIX)) {
                return (BindingResult)key.getValue();
            }
        }

        return null;
    }


}
公共静态最终字符串绑定\结果\刷新\属性\键=BindingHandlerInterceptor.class.getName()+“.flashBindingResult”; 私有静态最终字符串方法\u GET=“GET”; 私有静态最终字符串方法\u POST=“POST”; @凌驾 public void postHandle(HttpServletRequest请求、HttpServletResponse响应、对象处理程序、ModelAndView ModelAndView)引发异常{ if(METHOD_POST.equals(request.getMethod())){ BindingResult BindingResult=getBindingResult(modelAndView); FlashMap outFlash=RequestContextUtils.getOutputFlashMap(请求); if(bindingResult==null | | |!bindingResult.hasErrors()| | outFlash==null){ 返回; } 输出(绑定\结果\刷新\属性\键,绑定结果); } Map flash=RequestContextUtils.getInputFlashMap(请求); if(METHOD_GET.equals(request.getMethod())&&inFlash!=null&&inFlash.containsKey(BINDING_RESULT_FLUSH_ATTRIBUTE_KEY)){ BindingResult flashBindingResult=(BindingResult)inFlash.get(BINDING\u RESULT\u FLUSH\u ATTRIBUTE\u KEY); if(flashBindingResult!=null){ BindingResult BindingResult=getBindingResult(modelAndView); if(bindingResult==null){ 返回; } bindingResult.addAllErrors(flashBindingResult); } } } 公共静态BindingResult getBindingResult(ModelAndView ModelAndView){ if(modelAndView==null){ 返回null; } for(输入键:modelAndView.getModel().entrySet()){ if(key.getKey().startsWith(BindingResult.MODEL_key_PREFIX)){ return(BindingResult)key.getValue(); } } 返回null; } }
这忽略了问题的全部要点。他试图避免在帖子中返回屏幕,因为浏览器是如何处理发布的表单的。如果用户点击“刷新”或“返回”,则会重新发布表单,这可能会导致服务器上的状态被修改两次。使用get将它们重定向回原始表单要好得多。