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
相关产品推荐
相关产品推荐

