@Valid 注解不验证子对象列表
Posted
技术标签:
【中文标题】@Valid 注解不验证子对象列表【英文标题】:@Valid annotation is not validating the list of child objects 【发布时间】:2011-07-05 18:02:19 【问题描述】:主要模型类如下:
public class UserAddressesForm
@NotEmpty
private String firstName;
@NotEmpty
private String lastName;
private List<AddressForm> addresses;
// setters and getters
public class AddressForm
@NotEmpty
private String customName;
@NotEmpty
private String city;
@NotEmpty
private String streetAn;
@NotEmpty
private String streetHn;
@NotEmpty
private String addressCountry;
@NotEmpty
private String postCode;
// setters and getters
我的一个控制器中的一个端点:
@RequestMapping(value = "/up", method = RequestMethod.POST)
public String completeForm(@Valid @ModelAttribute("userAddressesForm") UserAddressesForm userAddressesForm,
BindingResult result, HttpServletRequest req)
// logic here
.jsp
页面:
<form:form commandName="userAddressesForm" action="registered">
<table>
<tr>
<td class="formLabels"><form:label path="firstName">
<spring:message code="label.name" />
</form:label></td>
<td><form:input path="firstName" /></td>
<td><form:errors path="firstName" cssClass="error" /></td>
</tr>
<tr>
<td class="formLabels"><form:label path="lastName">
<spring:message code="label.surname" />
</form:label></td>
<td><form:input path="lastName" /></td>
<td><form:errors path="lastName" cssClass="error" /></td>
</tr>
</table>
<c:forEach items="$userAddressesForm.addresses" varStatus="gridRow">
<div id="main_address" class="address_data_form">
<fieldset>
<legend><spring:message code="label.stepThreeMainAddressInfo" /></legend>
<a href="#" class="deleteItem"></a>
<table>
<tr>
<td class="formLabels">
<spring:message code="label.address.custom.name" />
</td>
<td>
<spring:bind path="addresses[$gridRow.index].customName">
<input type="input" name="<c:out value="$status.expression"/>"
id="<c:out value="$status.expression"/>"
value="<c:out value="$status.value"/>" />
<form:errors path="$status.expression"/>
</spring:bind>
</td>
</tr>
<tr>
<td class="formLabels">
<spring:message code="label.streetAnStreetHn" />
</td>
<td>
<spring:bind path="addresses[$gridRow.index].streetAn">
<input type="input" name="<c:out value="$status.expression"/>"
id="<c:out value="$status.expression"/>"
value="<c:out value="$status.value"/>" />
</spring:bind>
<spring:bind path="addresses[$gridRow.index].streetHn">
<input type="input" name="<c:out value="$status.expression"/>"
id="<c:out value="$status.expression"/>"
value="<c:out value="$status.value"/>" >
<form:errors path="addresses[$gridRow.index].streetHn"/>
</spring:bind>
</td>
</tr>
<tr>
<td class="formLabels">
<spring:message code="label.postCode" />
</td>
<td>
<spring:bind path="addresses[$gridRow.index].postCode">
<input type="input" name="<c:out value="$status.expression"/>"
id="<c:out value="$status.expression"/>"
value="<c:out value="$status.value"/>" />
</spring:bind>
</td>
</tr>
<tr>
<td class="formLabels">
<spring:message code="label.city" />
</td>
<td>
<spring:bind path="addresses[$gridRow.index].city">
<input type="input" name="<c:out value="$status.expression"/>"
id="<c:out value="$status.expression"/>"
value="<c:out value="$status.value"/>" />
<form:errors path="addresses[$gridRow.index].city" cssClass="error" />
</spring:bind>
</td>
</tr>
</table>
</fieldset>
</div>
</c:forEach>
为什么@Valid
没有验证UserAddressesForm
类中的List<AddressForm> addresses
?
【问题讨论】:
【参考方案1】:你需要用@Valid
注解来装饰UserAddressesForm
的addresses
成员。请参阅JSR 303: Bean Validation 的第 3.1.3 和 3.5.1 节。正如我在对问题 Is there a standard way to enable JSR 303 Bean Validation using annotated method 的回答中所解释的那样,这是根据 JSR 303 对 @Valid
注释的真正用途。
编辑 示例代码:Hibernate Validator- Object Graph。 (车内乘客名单)
编辑来自Hibernate Validator 6参考文档:
在 6 之前的版本中,Hibernate Validator 支持对容器元素的子集进行级联验证,并且它是在容器级别实现的(例如,您可以使用
@Valid private List<Person>
为Person
启用级联验证)。这仍然受支持,但不推荐。请使用容器 元素级别
@Valid
注释,因为它更具表现力。
例子:
public class Car
private List<@NotNull @Valid Person> passengers = new ArrayList<Person>();
private Map<@Valid Part, List<@Valid Manufacturer>> partManufacturers = new HashMap<>();
//...
还可以查看 Bean Validation 2.0/Jakarta Bean Validation 的新增功能。
【讨论】:
分组呢?我希望仅在验证 A 组时验证地址。@Valid
忽略该组。
@Akshay @Valid
注释在较低级别工作。我认为@GroupSequence 可以用来指定验证顺序。
我的详细问题***.com/q/41457404/1534925。不要认为顺序对我有用。【参考方案2】:
添加到@Ritesh 答案,@Valid
约束将指示 Bean 验证器深入研究其应用属性的类型并验证在那里找到的所有约束。用代码回答您的问题,验证器在看到addresses
属性上的@Valid
约束时,将探索AddressForm
类并验证内部找到的所有JSR 303
约束,如下所示:
public class UserAddressesForm
@NotEmpty
private String firstName;
@NotEmpty
private String lastName;
@Valid
private List<AddressForm> addresses;
...
setters and getters
public class AddressForm
@NotEmpty
private String customName;
@NotEmpty
private String city;
@NotEmpty
private String streetAn;
@NotEmpty
private String streetHn;
@NotEmpty
private String addressCountry;
@NotEmpty
private String postCode;
...
setters and getters
【讨论】:
分组呢?我希望仅在验证 A 组时验证地址。 @Valid 忽略组 我什至没有阅读您的答案,但只是看着setters and getters
解决了我的问题。【参考方案3】:
在 UserAddressesForm 类中添加以下行
@Valid
private List<AddressForm> addresses;
【讨论】:
【参考方案4】:工作解决方案。
public class UserAddressesForm
@NotEmpty(message="firstName is required")
private String firstName;
@NotEmpty(message="lastNameis required")
private String lastName;
@NotNull(message="addresses attributes are required")
@Valid
private List<AddressForm> addresses;
...
setters and getters
public class AddressForm
@NotEmpty(message="customNameis required")
private String customName;
@NotEmpty
private String city;
@NotEmpty
private String streetAn;
@NotEmpty
private String streetHn;
@NotEmpty
private String addressCountry;
@NotEmpty
private String postCode;
...
setters and getters
【讨论】:
【参考方案5】:我使用@Valid
实现了父类中的所有建议和注释子字段,但子实体仍未得到验证。
幸运的是它现在已解决,问题是由于依赖关系。 作为我在依赖项下使用的解决方案
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
而不是
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
【讨论】:
以上是关于@Valid 注解不验证子对象列表的主要内容,如果未能解决你的问题,请参考以下文章
validator 手动验证 表单字段 不基于注解@Valid
Kotlin Spring Boot Webflux 使用 @Valid 注解验证 @RequestBody