108

主要模型类如下:

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不在课堂上验证List<AddressForm> addresses现在UserAddressesForm

4

6 回答 6

180

您需要使用注释来装饰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 真正使用注释。UserAddressesForm@Valid@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中的新增功能。

于 2011-02-28T14:04:12.427 回答
31

添加到@Ritesh 答案中,@Valid约束将指示 Bean 验证器深入研究其应用属性的类型并验证在那里找到的所有约束。用代码回答您的问题,验证器在看到属性@Valid约束时addresses,将探索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
于 2016-10-05T15:52:53.197 回答
10

在 UserAddressesForm 类中添加以下行

@Valid
private List<AddressForm> addresses;
于 2019-02-16T21:59:40.287 回答
6

工作解决方案。

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
于 2019-04-26T20:42:04.167 回答
0

我用 with 实现了父类中的所有建议和带注释的子字段,@Valid但子实体仍未得到验证。

幸运的是它现在已经解决了,问题是因为依赖。作为我在依赖项下使用的解决方案

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

代替

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
于 2021-11-24T19:20:22.880 回答
0

对我来说,它是@NotNull, 在孩子身上,而不是@NotEmpty注释。我必须@NotNull在注释之前放一个才能@Valid使它起作用。

像这样:

private List<@NotNull @Valid YourObject> yourObjects;
于 2022-03-02T14:06:12.467 回答