JSR303(Bean Validation 1.0)

Bean Validation的1.0版本 

1、约束定义

1.1 约束注解

Constraint 可用于字段、方法、属性、类型、注解类型,validatedBy返回的是ConstraintValidator类型的数组

@Documented
@Target({ ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface Constraint {
/**
* <code>ConstraintValidator</code> classes must reference distinct target types.
* If two <code>ConstraintValidator</code> refer to the same type,
* an exception will occur.
*
* @return array of ConstraintValidator classes implementing the constraint
*/
public Class<? extends ConstraintValidator<?, ?>>[] validatedBy();
}

约束的属性有三个基本的

String message() default '';
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};

1.2 应用相同类型的多个约束

使用常规注解,value返回元素类型为约束注解的数组,并且注解的保留策略必须是RUNTIME。@Target 建议与初始约束有相同。

建议约束注解与多值注解耦合在一起

1.3 约束组合 

组合注解继承主约束注解的分组和payload

主注解如果想覆盖组合注解的属性,可以使用@OverridesAttribute或者@OverridesAttribute.List

@Retention(RUNTIME)
@Target({ METHOD })
public @interface OverridesAttribute {
    /**
        * @return Constraint type the attribute is overriding
    */
    Class<? extends Annotation> constraint();
    /**
        * Name of the Constraint attribute overridden.
        * Defaults to the name of the attribute hosting <code>@OverridesAttribute</code>.
        *
        * @return name of constraint attribute overridden.
    */
    String name();
    /**
        * The index of the targeted constraint declaration when using
        * multiple constraints of the same type.
        * The index represents the index of the constraint in the value() array.
        *
        * By default, no index is defined and the single constraint declaration
        * is targeted
        *
        * @return constraint declaration index if multivalued annotation is used
    */
    int constraintIndex() default -1;
    /**
        * Defines several @OverridesAttribute annotations on the same element
        * @see javax.validation.OverridesAttribute
    */
    @Documented
    @Target({ METHOD })
    @Retention(RUNTIME)
    public @interface List {
        OverridesAttribute[] value();
    }
}

1.4 约束校验实现

通过注解@Contraint(validatedBy=<class>)指定

class需要实现ConstraintValidator泛型接口

T不能是参数化类型或者T的泛型参数必须是无界通配符

 相关类图:

2、约束声明及校验处理

约束在类型上声明,评估实例或者实例图。

2.1 待验证类的要求

  • 属性需要遵循JavaBean读取属性的方法签名约定
  • 静态字段和方法不在校验范围内
  • 约束可以用于接口和超类

注解定义的目标可以是字段,属性或者类型,前提是:

  • 约束定义支持指定的目标类型(java.lang.annotation.Target)
  • 约束中声明的其中一个ConstraintValidator支持声明的目标类型

2.1.1 对象验证

约束声明用于类或者接口上。对类或接口应用约束表示对类或实现接口的类的状态的验证

2.1.2 字段和属性验证

约束声明可以应用于同一类型的字段和属性上。在字段和相关属性上同一约束不应该重复。推荐持有约束声明的对象绑定到单状态访问策略。

字段和方法的可见性不受约束。

2.1.3 图验证

图的结果验证作为一组统一的约束冲突返回。使用@Valid注解。

集合、数组、迭代器的字段和属性也可以用@Valid装饰。

2.2 约束声明

约束声明通过注解放在类或者接口上。约束注解可以应用于类型上、类型字段以及遵循JavaBean的属性上。

约束声明定义在类上,需要验证的类实例会传递给ConstraintValidator。

约束定义在字段上,字段值传递给ConstraintValidator

约束定义在getter方法上,getter方法的返回值传递给ConstraintValidator

2.3 继承(接口和超类)

约束声明放在接口上,对于给定类,约束声明放在超类上。

约束声明的影响是累加的。将验证在超类getter上声明的约束以及根据Java语言规范可见性规则在getter的重写版本上定义的任何约束

2.4 组和组序列

组定义约束子集。不是验证给定对象图的所有约束,只是验证其中的子集。子集通过目标组或者组群定义。每个约束声明定义所属的组列表。如果没有指定,属于Default组。

组由接口表示。

约束可以属于一个或者多个组。

2.4.1 组继承

在某些情况下,组是一个或者多个组的超集。组可以通过接口继承来继承一个或者多个组。

2.4.2 组序列

默认情况下,不管属于哪个组,约束检查没有固定的顺序。

通过注解@GroupSequence来指定次序。

组的组合不应该有环依赖。如果包含环依赖,验证计算时会抛出GroupDefinitionException异常。

定义了次序的组不应该直接继承其它组(即持有组序列的接口不应该有超接口)

定义了次序的组不应该直接用在约束声明中。

为了定义一个组为序列,接口必须用注解@GroupSequence标注

@Target({ TYPE })
@Retention(RUNTIME)
public @interface GroupSequence {
    Class<?>[] value();
}

2.4.3 为类重新定义默认组

重新定义类的默认组,在类上使用@GroupSequence注解。

定义在类A上的序列必须包含组A(在类上的默认注解必须是序列定义的一部分)。当@GroupSequence为类A定义Default组,但是不包含组A,当类验证时或者请求元数据是会抛出GroupDefinitionException异常。

2.4.4 隐式分组

接口Z上承载的每个约束以及默认组的一部分(隐式或显式)都属于组Z

2.4.5 正式组定义

对于每个类X

  • 对于X的每个超类Y,Y组包含Y的组Y的所有约束
  • 组X包含以下约束

         组X是用于重新定义类上默认组的序列的组

  1. 类X声明的每个约束都没有声明组或显式声明组默认值,所有都是Default
  2. 由X实现的任何接口声明的每个约束,且未注释@GroupSequence不显式声明组或显式声明组默认值,X的接口上承载的所有默认约束被X继承。将忽略标记为@GroupSequence的接口

  3. 如果X有一个直接超类Y,则组Y中的每个约束,X的超类上承载的所有默认约束,由类层次结构继承

  • 如果X没有@GroupSequence注释,则组默认值包含以下约束

        此规则定义在验证X上的默认值时计算哪些约束

  1. 组X中的每个约束
  2. 如果X有一个直接超类Y,则Y中默认组的每个约束

        如果Y重新定义组默认值,则此规则是必需的

  • 如果X有@GroupSequence注释,则组默认值包含属于每个由@GroupSequence注释声明的组,@GroupSequence注释必须声明组X

  • 对于每个接口Z,组Z包含以下约束

  1. 接口Z声明的每个约束,这些约束没有显式声明组或组默认值显式,位于接口Z上的所有默认约束:该规则正式定义了每个接口的隐式分组

  2. 由z的任何没有注释@GroupSequence的超级接口声明的每个约束(不显式声明组),Z的接口上承载的所有默认约束:组可以被继承

  3. 类X声明的每个约束,它显式声明了组Z,由X承载并标记了的每个约束属于组Z

  4. 由X实现的任何接口声明的每个约束,且未注释@GroupSequence显式声明组Z,由X承载并标记了的每个约束属于组Z

  5. 如果X有一个直接超类Y,则Y的Z组中的每个约束,由X的任何超类承载并标记了的每个约束为属于组Z

  • 对于每个注解了@GroupSequence的接口z,组z包含了属于注解@GroupSequence声明的每个组的每个约束。

2.5 验证过程

验证指定组,应用于指定bean实例的验证过程会执行如下的约束验证:

  • 所有可到达的字段,执行符合组的字段级别的验证
  • 所有可到达的getter要,执行所有指定符合组的getter级别的验证。
  • 执行所有匹配目标组的类级别的验证。
  • 对于所有可到达的以及级联的关系,执行所有级联的验证。

2.5.1 可遍历的属性

3、Validation API

4、元数据请求API

5、内置约束定义

@Null
@NotNull
@AssertTrue
@AssertFalse
@Min
@Max
@DecimalMin
@DecimalMax
@Size
@Digits
@Past
@Future
@Pattern

参考资料:

https://beanvalidation.org/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值