描述内容

1 对于简单类型参数(非Bean),直接在参数前,使用注解添加约束规则。比如 @NotNull @Length 等
2 在类名前追加 @Validated 注解,否则添加的约束规则不生效。
3 方法被调用时,如果传入的实际参数与约束规则不符,会直接抛出 MethodArgumentNotValidException(Controller层)
ConstraintViolationException (Service层),表明参数校验失败
4 对于Bean类型的参数,在Bean内部的各个字段上面追加约束注解,然后在方法的参数前面添加 @Valid 注解即可。

这里先说下基于Controller层的注解使用

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_java


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_02

上面说的是常规注解使用,为了异常统一返回 这里需要一个异常统一处理类、还需要一个返回值返回封装类

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring boot_03


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_04


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_05

5 对于Bean里面套Bean的级联校验用法如下,在外层Bean里面写@Valid即可。

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_约束规则_06


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_07

如果是类似list、map等的级联校验 注解加入如下图所示

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_08

实验效果如下:

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_错误提示_09

常用校验注解

@Null(groups={Add.class}) 参数必须为null,group设置分组,默认为default
@NotNull 参数不为null
@NotEmpty 参数不为null ,"",集合不为空
@NotBlank 参数不为null, "", " ",只能作用字符串类型
@AssertFalse 被注释的元素必须是false
@AssertTrue 被注释的元素必须是true
@Min(value) 被注释的元素必须为一个数字  >=
@Max(value) 被注释的元素必须为一个数字 <= 
@DecimalMin("value")  >=
@DecimalMax("value") <= 
@NegativeOrZero <=0
@Range(min,max) 被注释的元素大小必须在指定的范围内 
@Size(min ,max) 被注释的元素大小必须在指定的范围内
@Email 被注释的元素必须是电子邮箱地址
@Past 被注释的元素必须是一个过去的日期
@PastOrPresent  被注释的元素必须是一个过去的时间
@Future 被注释的元素必须是一个将来的日期
@Pattern(regexp = "1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\\d{8}$")  被注释的元素必须是符合指定的正则表达式
@URL 被注释的元素必须是链接地址


备注:参数校验只有!= null的时候才生效

导入如下依赖
		<dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>

注意

1 约束用的注解,一般需要带上message参数方便自定义错误信息,比如前面例子中的“@NotNull(message = “姓名不能为空”)”。而这个message参数是支持EL表达式的

@NotNull(message = "${member.id.null}") 

再定义一个比如叫做 messages.properties 的配置文件来统一管理错误信息

member.id.null=用户编号不能为空

2 约束规则支持正则表达式

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring boot_10

3 基于service层面注解使用如下:

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_11

1.直接使用service实现类

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring boot_12

需要在统一异常处理类里面增加异常处理方法

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_13

2.基于service接口、实现类的

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_错误提示_14


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_约束规则_15

4.分组校验 用来区分实体类中某些字段需要参与校验某些字段不需要参与校验

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_16


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_约束规则_17


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_java_18

注意:

@Validated({ValidationTest.Adult.class,Default.class
}注解里面如果没有加入Default.class
则只会生效属性上面注解 @Min(value = 18,groups = {Adult.class})
的属性

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_19


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_错误提示_20

5.自定义注解

添加一个“时间格式校验”的限制

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_java_21

我们不需要关注太多东西,使用spring validation的原则便是便捷我们的开发,例如payload,List ,groups,都可以忽略。

<1> 自定义注解中指定了这个注解真正的验证者类

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_22

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_错误提示_23


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring_24

自定义效验的验证者编写规则

所有的验证者都需要实现ConstraintValidator接口,它的接口也很形象,包含一个初始化事件方法,和一个判断是否合法的方法

public interface ConstraintValidator<A extends Annotation, T> {

    void initialize(A constraintAnnotation);

    boolean isValid(T value, ConstraintValidatorContext context);
}

<2> ConstraintValidatorContext 这个上下文 包含了认证中所有的信息,我们可以利用这个上下文实现获取默认错误提示信息禁用错误提示信息改写错误提示信息等操作

<3> 一些典型校验操作,或许可以对你产生启示作用。 值得注意的一点是,自定义注解 可以用在METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER之上,ConstraintValidator的第二个泛型参数T,是需要被校验的类型

实现类写好之后直接在需要的实体属性上面使用注解即可

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring boot_25

6.使用JSR提供的@GroupSequence注解控制校验顺序

上面是Hibernate Validation提供的能力,而不是JSR标准提供的。@GroupSequence 它是JSR标准提供的注解(只是没有provider强大而已,但也有很适合它的使用场景)

// Defines group sequence.  定义组序列(序列:顺序执行的)
@Target({ TYPE })
@Retention(RUNTIME)
@Documented
public @interface GroupSequence {
    Class<?>[] value();
}

顾名思义,它表示Group组序列。默认情况下,不同组别的约束验证是无序的,在某些情况下,约束验证的顺序是非常的重要的,比如如下两个场景:

  • 第二个组的约束验证依赖于 第一个约束执行完成的结果必须第一个约束正确了,第二个约束执行才有意义
  • 某个Group组的校验非常耗时,并且会消耗比较大的CPU/内存。那么我们的做法应该是把这种校验放到最后,所以对顺序提出了要求

一个组可以定义为其他组的序列,使用它进行验证的时候必须符合该序列规定的顺序。在使用组序列验证的时候,如果序列前边的组验证失败,则后面的组将不再给予验证

使用如下:

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_约束规则_26


spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_spring boot_27

这里的分组顺序是先校验年龄大小 ,年龄校验通过后才会校验默认参数

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_java_28

年龄校验通过:

spring boot 在函数中 对实体对象的属性值 校验 springboot参数校验注解_java_29