文章目录
前言
Spring Validation验证框架对参数的验证机制提供了@Validated(Spring’s JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果。其中对于字段的特定验证注解比如@NotNull等。
在检验Controller的入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同。
注解使用
@Validated
可以用在类型、方法和方法参数上,但是不能用在成员属性(字段)上
@Valid:
可以用在方法、构造函数、方法参数和成员属性(字段)上(支持嵌套验证)
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。
参数嵌套验证
我们创建一个企业发票入参类CompanyInvoiceParam 和发票具体详情类Invoice,另外,为了方便验证返回的错误信息,添加一个全局异常类GlobalExceptionHandler ,创建controller测试接口testValid
@RestControllerAdvice
public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST) //设置状态码为 400
@ExceptionHandler({MethodArgumentNotValidException.class})
public String paramExceptionHandler(MethodArgumentNotValidException e) {
BindingResult exceptions = e.getBindingResult();
// 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
if (exceptions.hasErrors()) {
List<ObjectError> errors = exceptions.getAllErrors();
if (!errors.isEmpty()) {
// 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
FieldError fieldError = (FieldError) errors.get(0);
return fieldError.getDefaultMessage();
}
}
return "请求参数错误";
}
}
1、 入参仅添加@Validated
@Data
public class CompanyInvoiceParam implements Serializable {
@NotBlank(message = "企业名称不得为空不能为空")
private String companyName;
@NotNull(message = "发票数据不得为空")
private List<Invoice> invoiceList;
}
@Data
public class Invoice implements Serializable {
@NotNull(message = "发票金额不得为空")
private BigDecimal amount;
}
@PostMapping(value = "/testValid", produces = MediaType.APPLICATION_JSON_VALUE)
public void testValid(@Validated @RequestBody CompanyInvoiceParam companyInvoiceParam) {
System.out.println("入参校验");
}
测试结果:
发票数据为空,能够正常校验
嵌套的发票数据里的字段为空,无法校验
2、 入参仅添加@Valid
@Data
public class CompanyInvoiceParam implements Serializable {
@NotBlank(message = "企业名称不得为空不能为空")
private String companyName;
@NotNull(message = "发票数据不得为空")
private List<Invoice> invoiceList;
}
@Data
public class Invoice implements Serializable {
@NotNull(message = "发票金额不得为空")
private BigDecimal amount;
}
@PostMapping(value = "/testValid", produces = MediaType.APPLICATION_JSON_VALUE)
public void testValid(@Valid @RequestBody CompanyInvoiceParam companyInvoiceParam) {
System.out.println("入参校验");
}
测试结果:
发票数据为空,能够正常校验(同1一样)
嵌套的发票数据里的字段为空,无法校验(同1一样)
3、 入参仅添加@Validated,内嵌字段上用@Valid
@Data
public class CompanyInvoiceParam implements Serializable {
@NotBlank(message = "企业名称不得为空不能为空")
private String companyName;
@Valid
@NotNull(message = "发票数据不得为空")
private List<Invoice> invoiceList;
}
@Data
public class Invoice implements Serializable {
@NotNull(message = "发票金额不得为空")
private BigDecimal amount;
}
@PostMapping(value = "/testValid", produces = MediaType.APPLICATION_JSON_VALUE)
public void testValid(@Validated @RequestBody CompanyInvoiceParam companyInvoiceParam) {
System.out.println("入参校验");
}
测试结果:
发票数据为空,能够正常校验
嵌套的发票数据里的字段为空,能够正常校验
总结
● @Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
● @Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
若有嵌套的类参数验证,需要在字段上加上@Valid,controller接口入参用@Valid或@Validated都可以