You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring:如何重定向URL且不重置表单输入内容

表单提交出错后保留输入内容的两种解决方案

一、重定向时保留表单数据(使用Spring Flash Attributes)

重定向会发起新的GET请求,原POST请求的Model数据无法直接传递,Spring的Flash Attributes可以解决这个问题——它会把数据暂存在Session中,重定向完成后自动取出并清除Session中的数据。

修改POST接口代码

把原来的ModelMap换成RedirectAttributes,在异常捕获时将表单数据和错误信息存入Flash:

@RequestMapping(value=POST_FORM, method=RequestMethod.POST)
public String postForm(
        @ModelAttribute("createForm") StoreDto form, 
        @PathVariable String channelCode, 
        Authentication authentication, 
        RedirectAttributes redirectAttributes) {

    UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
    
    try {
        form.setClientId(userPrincipal.getUser().getClient().getId());
        ruleService.save(form);
    }catch(Exception e) {
        // 存入表单数据和错误信息到Flash
        redirectAttributes.addFlashAttribute("createForm", form);
        redirectAttributes.addFlashAttribute("err", e.getClass().getSimpleName());
        return "redirect:/config/"+form.getChannelCode()+"/form/create";
    }
    return "redirect:/config/"+form.getChannelCode()+"/list";
}

修改表单页面的GET接口代码

添加参数接收Flash中的表单数据,并将其放入Model供页面回显:

@GetMapping(CREATE_FORM)
public String createForm(@PathVariable String channelCode, 
                        @RequestParam(required = false) String error, 
                        Authentication authentication, 
                        ModelMap model,
                        @ModelAttribute(value = "createForm", required = false) StoreDto form) {
    
    UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
    SalesDto salesDto = salesService.findByClientIdAndChannelCode(userPrincipal.getUser().getClient().getId(), channelCode);
    List<StoreDto> storeDtos = ruleService.findAllRuleStoreByClientIdAndChannelCode(userPrincipal.getUser().getClient().getId(), channelCode);
    
    model.addAttribute("channel", salesDto);
    model.addAttribute("stores", storeDtos);
    
    // 优先使用Flash中的错误信息,其次是URL参数中的
    if (model.containsAttribute("err")) {
        model.addAttribute("err", model.getAttribute("err"));
    } else if (error != null) {
        model.addAttribute("err", error);
    }
    
    // 如果有Flash传递的表单数据,回显到页面
    if (form != null) {
        model.addAttribute("createForm", form);
    }
    
    return "configuration/form_create";
}

二、无需重定向的替代方案

如果不想用重定向,直接在POST接口异常时返回表单视图,同时将用户输入的表单数据和页面所需的其他数据重新放入Model,就能直接保留输入内容。

修改POST接口代码

异常捕获时,重新填充表单页面的公共数据,把用户输入的表单数据放回Model,然后直接返回表单视图:

@RequestMapping(value=POST_FORM, method=RequestMethod.POST)
public String postForm(
        @ModelAttribute("createForm") StoreDto form, 
        @PathVariable String channelCode, 
        Authentication authentication, 
        ModelMap model) {

    UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
    
    try {
        form.setClientId(userPrincipal.getUser().getClient().getId());
        ruleService.save(form);
        return "redirect:/config/"+form.getChannelCode()+"/list"; // 成功提交后仍重定向,避免重复提交
    }catch(Exception e) {
        // 填充表单页面所需的公共数据
        SalesDto salesDto = salesService.findByClientIdAndChannelCode(userPrincipal.getUser().getClient().getId(), channelCode);
        List<StoreDto> storeDtos = ruleService.findAllRuleStoreByClientIdAndChannelCode(userPrincipal.getUser().getClient().getId(), channelCode);
        
        model.addAttribute("channel", salesDto);
        model.addAttribute("stores", storeDtos);
        model.addAttribute("err", e.getClass().getSimpleName());
        model.addAttribute("createForm", form); // 回显用户输入的表单数据
        
        return "configuration/form_create"; // 直接返回表单视图,不重定向
    }
}

优化建议:抽取公共代码

为了避免重复代码,可以把填充公共数据的逻辑抽成私有方法:

private void populateFormCommonData(UserPrincipal userPrincipal, String channelCode, ModelMap model) {
    SalesDto salesDto = salesService.findByClientIdAndChannelCode(userPrincipal.getUser().getClient().getId(), channelCode);
    List<StoreDto> storeDtos = ruleService.findAllRuleStoreByClientIdAndChannelCode(userPrincipal.getUser().getClient().getId(), channelCode);
    model.addAttribute("channel", salesDto);
    model.addAttribute("stores", storeDtos);
}

之后在createForm方法和postForm的异常块中调用这个方法即可。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:30:53