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

Spring Boot中Spring MVC多动态表单的@Valid校验实现咨询

实现动态添加家庭成员表单的@Valid校验方案

1. 重构模型结构

首先要把家庭成员抽成独立实体类,同时在主申请表单中添加家庭成员列表并启用嵌套校验,这样Spring才能识别并校验动态添加的多表单数据。

创建Dependent实体类

@Entity
public class Dependent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @NotBlank(message = "家庭成员姓名不能为空")
    private String name;

    @Size(min = 5, message = "家庭成员描述至少5个字符")
    private String description;

    @ManyToOne
    @JoinColumn(name = "application_form_id")
    private ApplicationForm applicationForm;

    public Dependent() {}

    public Dependent(String name, String description) {
        this.name = name;
        this.description = description;
    }

    // 自行补充getter、setter方法
}

修改ApplicationForm实体类

添加家庭成员列表,并用@Valid触发嵌套校验,同时配置JPA一对多关联:

@Entity
public class ApplicationForm {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @NotBlank(message = "主申请人姓名不能为空")
    private String name;

    @Size(min = 5, message = "描述至少5个字符")
    private String description;

    private String bearer;

    // @Valid注解让Spring递归校验列表中每个Dependent对象
    @Valid
    @OneToMany(mappedBy = "applicationForm", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Dependent> dependents = new ArrayList<>();

    public ApplicationForm(int id, String name, String description, String bearer) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.bearer = bearer;
    }

    public ApplicationForm() {}

    // 补充dependents的getter、setter
    public List<Dependent> getDependents() {
        return dependents;
    }

    public void setDependents(List<Dependent> dependents) {
        this.dependents = dependents;
    }

    // 自行补充其他字段的getter、setter和toString方法
}

2. 修正JSP页面

补充家庭成员容器div,同时添加每个动态字段的错误提示:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>家庭档案提交</title>
</head>
<body>
    <div>
        <form:form modelAttribute="applicationForm" method="post">
            <form:input type="hidden" path="id" />
            <form:input type="text" path="bearer" placeholder="共用Bearer" />
            
            <form:label path="name">主申请人姓名:</form:label>
            <form:input type="text" path="name" />
            <form:errors path="name" cssStyle="color:red;" />
            
            <form:label path="description">主申请人描述:</form:label>
            <form:input type="text" path="description" />
            <form:errors path="description" cssStyle="color:red;" />
            
            <br/>
            <!-- 家庭成员表单容器 -->
            <div id="dependents"></div>
            <br/>
            <button type="button" onclick="addDependent()">添加家庭成员</button>
            <input type="submit" value="保存" />
        </form:form>
    </div>
    <script type="text/javascript">
        function addDependent() {
            var dependentsDiv = document.getElementById('dependents');
            var index = dependentsDiv.children.length;

            var newDependent = `
                <div class="dependent">
                    <form:hidden path="dependents[${index}].id" />
                    <form:label path="dependents[${index}].name">姓名:</form:label>
                    <form:input path="dependents[${index}].name" />
                    <form:errors path="dependents[${index}].name" cssStyle="color:red;" />
                    <br/>
                    <form:label path="dependents[${index}].description">描述:</form:label>
                    <form:input path="dependents[${index}].description" />
                    <form:errors path="dependents[${index}].description" cssStyle="color:red;" />
                    <br/>
                </div>
            `;
            dependentsDiv.innerHTML += newDependent;
        }
    </script>
</body>
</html>

3. 调整Controller

原有Controller只需小幅修改,确保初始化空列表并关联主表单:

@Controller
public class HomeController {

    @Autowired
    private FormRepository repo;

    @GetMapping("form")
    public String formPage(ModelMap modelMap) {
        ApplicationForm appForm = new ApplicationForm(0, "user", "", "");
        // 初始化空列表避免页面绑定报错
        appForm.setDependents(new ArrayList<>());
        modelMap.put("applicationForm", appForm);
        return "formpage";
    }

    @PostMapping("form")
    public String saveForm(@Valid ApplicationForm applicationForm, BindingResult result, ModelMap modelMap) {
        if (result.hasErrors()) {
            return "formpage";
        }
        // 绑定每个家庭成员与主表单的关联
        for (Dependent dependent : applicationForm.getDependents()) {
            dependent.setApplicationForm(applicationForm);
        }
        repo.save(applicationForm);
        return "redirect:/homepage";
    }
}

核心原理说明

  • @Valid标注在集合字段上时,Spring Validation会自动遍历集合内的每个对象,执行其内部的校验规则(如Dependent类的@NotBlank、@Size)。
  • JSP中使用dependents[${index}].fieldName的格式,Spring MVC会自动将动态表单数据绑定到列表对应位置的对象中。
  • JPA的@OneToMany配置确保主表单和家庭成员数据能被级联保存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:07:04