You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring项目中页面刷新时如何防止数据重复提交?PRG模式解决方案求助

解决Spring MVC刷新结果页数据重复问题(PRG模式实践)

你遇到的这个问题是Web开发里非常典型的POST重复提交场景——当你在结果页刷新时,浏览器会重新发送之前的POST请求,导致service.create(formData)被再次执行,数据自然就重复了。咱们用**PRG模式(Post/Redirect/Get)**就能完美解决这个问题,我给你拆解下怎么改代码:

问题根源分析

你当前的processForm方法在表单验证通过后,直接用mv.setViewName("result")做了服务器端转发(forward),这时候浏览器地址栏仍然是/send-form-data这个POST请求的地址。刷新页面时,浏览器会重新发送一次POST请求,重复执行数据插入逻辑,最终导致数据重复。

PRG模式解决方案

PRG的核心思路是:处理完POST提交后,不要直接返回结果视图,而是重定向到一个GET请求的结果页面。这样浏览器地址栏会变成GET请求的地址,后续刷新只会发送GET请求(仅做数据查询,不会执行插入操作),从根本上避免重复提交。

修改步骤及代码示例

  1. 改造POST请求处理方法
    将原来直接返回result视图的逻辑,改成重定向到一个新的GET请求接口,同时可以用RedirectAttributes传递临时数据(比如提交成功的表单数据,可选):

    @RequestMapping(value = "/send-form-data", method = RequestMethod.POST)
    public String processForm(@Valid @ModelAttribute("formData") SampleModel formData, 
                             BindingResult res, 
                             RedirectAttributes redirectAttributes) {
        fmv.validate(formData, res);
        
        if(res.hasErrors()) {
            // 验证失败,返回表单页面(这里用forward没问题,刷新只是重新加载表单)
            return "mainPage";
        } else {
            // 执行数据插入操作(只执行一次)
            service.create(formData);
            // 可选:用FlashAttribute传递临时数据,重定向后能在GET方法中获取
            redirectAttributes.addFlashAttribute("submittedData", formData);
            // 重定向到结果页的GET请求
            return "redirect:/show-results";
        }
    }
    
  2. 新增结果页的GET请求处理方法
    专门写一个GET接口来负责查询数据并返回结果视图,这样刷新页面时只会执行数据查询逻辑:

    @RequestMapping(value = "/show-results", method = RequestMethod.GET)
    public ModelAndView showResults() {
        ModelAndView mv = new ModelAndView("result");
        // 查询最新的数据列表
        mv.addObject("list", service.findAll());
        // 如果需要使用之前传递的表单数据,可从FlashAttribute中获取
        // SampleModel submittedData = (SampleModel) mv.getModel().get("submittedData");
        return mv;
    }
    

为什么这样改就有效?

  • 当表单提交成功后,服务器返回重定向响应,浏览器会自动发送一个GET请求到/show-results,地址栏也会更新为这个GET地址。
  • 后续刷新页面时,浏览器只会重新发送这个GET请求,而GET请求的逻辑只是查询数据,不会执行service.create(formData)插入操作,自然就不会出现数据重复的问题了。

内容的提问来源于stack exchange,提问作者can

火山引擎 最新活动