我几天来一直试图在网上找到类似的问题,但似乎什么都找不到,所以我在这里问我的问题。
我有一个控制器:
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Validated
@RestController
@RequestMapping("/data")
public class TheController {
private final TheService theService;
@Autowired
public TheController(TheService theService) {
this.theService = theService;
}
@PostMapping(path = "/data", consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.TEXT_PLAIN_VALUE})
public ResponseEntity<String> saveData(@Valid @RequestBody Data data) {
subscriptionDataFeedService.sendData(data.getDataList());
return ResponseEntity.ok()
.body("Data successful.");
}
}
我有请求主体类:
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Data {
@NotEmpty(message = "Data list cannot be empty.")
@JsonProperty(value = "dataArray")
List<@Valid DataOne> dataList;
}
我有DataOne类:
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class DataOne {
private @NotBlank String currency;
private @NotBlank String accountNumber;
private @NotBlank String finCode;
private String poNumber;
private @NotBlank String invoiceNumber;
private @NotNull Address billTo;
private @NotNull Address soldTo;
private @NotNull LocalDate invoiceDate;
private @NotBlank String billingPeriod;
private @NotNull LocalDate paymentDueDate;
private @NotNull BigDecimal amountDue;
@JsonProperty(value = "activitySummary")
private @NotNull List<@Valid ProductSummary> productSummaryList;
@JsonProperty(value = "accountSummary")
private @NotNull List<@Valid AccountSummary> accountSummaryList;
@JsonProperty(value = "transactions")
private @NotNull List<@Valid Transaction> transactionList;
private @NotNull PaymentByACH paymentByACH;
private @NotNull Address paymentByCheck;
private @NotNull CustomerServiceContact customerServiceContact;
}
我将包括地址类:
import javax.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Address {
private @NotBlank String name;
private @NotBlank String address1;
private String address2;
private @NotBlank String city;
private @NotBlank String state;
private @NotBlank String postalCode;
}
我省略了其他一些课程,因为我的问题不需要它们。
因此,我遇到的问题是@Valid注释能够验证除了DataOne中不是列表的嵌套类的之外的所有。换句话说,它无法验证Address、PaymentByACH等内部的字段。但是,它能够验证这些对象是否为@NotNull,但无法验证这些类内部的字段。
@Valid无法验证address中的名称、地址1、城市等字段。每当我在DataOne内的Address字段前面添加@Valid标记时,我都会在isValid调用异常期间得到HV000028:意外异常。
如何验证Address对象或任何嵌套对象内部的嵌套字段?
TL;DR:作为列表的对象(如List<@Valid Transaction> transactionList;
(会验证Transaction内部的字段,但代码不会验证Address内部的字段。
好问题。
我认为您有点滥用了@Valid
注释。
如何验证Address对象内部的嵌套字段或有嵌套的对象吗?
@Valid
不应作为要验证的字段的前缀该工具专门用于验证@Controller
端点方法(有时还有@Service
方法(中的参数。根据docs.spring.io:
"Spring MVC具有自动验证@Controller的能力输入">
它提供了以下示例,
@Controller
public class MyController {
@RequestMapping("/foo", method=RequestMethod.POST)
public void processFoo(@Valid Foo foo) { /* ... */ }
}
除了在控制器(或服务(方法的参数之外,您应该在任何地方使用@Valid
的唯一原因是注释复杂类型,如对象列表(即:DataOne:productSummaryList、accountSummaryList和transactionList(。如果您愿意,这些文档提供了实现您自己的验证策略的详细信息。
为了满足您的实际需要,您可能只应该在控制器级别的方法和该方法引用的模型的复杂类型上使用@Valid
。然后使用字段级别的约束来确保你不会得到像负年龄这样的东西。例如:
@Data
...
public class Person {
...
@Positive
@Max(value = 117)
private int age;
...
}
从spring文档中查看可以使用的约束列表。您已经在使用@NotNull
约束,所以它不应该太外来。您可以验证电子邮件、信用卡、日期、小数、范围、负值或正值以及许多其他约束。