@Validated和@Valid的区别主要体现在3个方面:
@Valid与@Validated都是用来校验接收参数的。
@Valid是使用Hibernate validation的时候使用
@Validated是只用Spring Validator校验机制使用
说明:java的JSR303声明了@Valid这类接口,而Hibernate-validator对其进行了实现。
@Validated与@Valid区别:
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上,不支持嵌套检测
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上,支持嵌套检测
注意:SpringBoot使用@Valid注解需要引入如下POM
org.springframework.boot
spring-boot-starter-validation
@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。没有添加分组属性时,默认验证没有分组的验证属性。
@Valid:作为标准JSR-303规范,还没有吸收分组的功能。
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。
@Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
@Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
SpringBoot + validator参数校验
Hibernate Validate是Bean Validation实现的,内置了JSR303/JSR380中所有的constraint的实现,同时也额外提供了很多自定义的constraint。Bean Validation为JavaBean的验证提供了很多相关的元数据模型和API。
参数说明
在Hibernate Validate提供了很多注解,以实现对应参数的校验。
参数 | 描述 |
---|---|
@Null | 参数必须为null |
@NotNull | 参数不能为null |
@NotBlank | 参数不能为null和空值,一般作用在字符串类型 |
@AssertTrue | 参数必须为true |
@AssertFalse | 参数必须为false |
@Min(value) | 参数必须是数字,且大于等于指定的最小值 |
@Max(value) | 参数必须是数字,且小于等于指定的最大值 |
@DecimalMin(value) | 参数必须是数字,且大于等于指定的最小值 |
@DecimalMax(value) | 参数必须是数字,且小于等于指定的最大值 |
@Length(min,max) | 指定字符长度,最小值是多少,最大值是多少 |
@Size(max,min) | 参数的大小必须在指定的范围 |
@Digits(Integer,fraction) | 参数必须是个数字,且大小必须在可接受范围内 |
@Past | 参数必须是一个过去的日期 |
@Future | 参数必须是一个将来的日期 |
@Pattern(value) | 参数必须符合指定的正则表达式 |
参数必须符合电子邮箱地址 | |
@NotEmpty | 参数必须非空 |
@Range | 参数必须在合适的范围内 |
快速开始
在SpringBoot中使用Hibernate Validate特别简单,只需要引入jar包即可。
mavan引入:
org.hibernate.validator
hibernate-validator
6.2.3.Final
gradle引入:
implementation group: 'org.hibernate.validator', name: 'hibernate-validator', version: '6.2.3.Final'
封装统一异常处理类:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler({ConstraintViolationException.class, MethodArgumentNotValidException.class})
public ResultUtil resolveViolationException(Exception ex){
StringJoiner messages = new StringJoiner(",");
if (ex instanceof ConstraintViolationException){
Set updateUserInfo(@Validated(value = UserInfo.Update.class) @RequestBody UserInfo userInfo){
return ResultUtil.success(userInfo.toString());
}
在@Validated中value指定实体中定义的接口。
输出:
自定义校验
在参数校验时,可能Hibernate Validate自带的校验规则并不能满足我们业务需求,此时我们可以实现自定义校验规则。
需求:对身份证进行校验。
定义注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER,ElementType.FIELD})
@Constraint(validatedBy = IdCodeValidator.class)
public @interface IdCode {
String message() default "请填写正确的身份证信息";
Class[] groups() default {};
Class definedEmployeeInfo(@Validated @RequestBody Employee employee){
return ResultUtil.success(employee.toString());
}
在Employee中添加校验注解:
@Data
public class Employee {
@NotBlank(message = "请填写雇员名称")
private String name;
@IdCode(message = "请填写正确的身份证信息!")
private String idCode;
}
输出:
输入了错误的身份证,则校验不通过,提示定义的信息。
在日常工作中,使用Hibernate Validate进行参数校验真的会事半功倍,同时也提供了自定义校验的实现,让我们更加专注于业务。