Validatition 校验注解总结

Validation 注解

JSR

JSR (java Specification Requests) java规范提案,是指向JCP提出新增一个标准化技术规范的请求。任何人都可以提交JSR,向Java平台新增API和服务。

JCP

JCP (java Community Process) 是一个开放的国际组织,主要由java开发者以及被授权者组成,职能是发展和更新JCP维护的规范,规范包括J2ME,J2SE,J2EE,XML,OSS,JAIN 等。组织成员可以提交JSR,通过特定程序后,可将提交内容维护到到下一版本的规范里面。

JSR303

JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。

Bean Validation

Bean Validation 是一个运行时的数据验证框架,在验证之后的错误信息会被马上返回。它为JavaBean定义了相应的元数据模型和API。在应用程序中,通过使用Bean Validation或是你自己定义的constraint,就可以确保数据模型(JavaBean) 的正确性。constraint 可以附加到字段,getter方法,类或者接口上面。对于一些特定的需求,用户可以很容易的开发定制化的constraint。(实现基于JSR303框架提供的API以及服务)

Hibernate Validation

Hibernate Validation 是Bean Validation 的参考实现。它提供了JSR303 规范中所有内置Constraint的实现,除此之外还有一些附加的constraint。

maven 依赖包

<!--jsr 303-->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<!-- hibernate validator-->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.2.0.Final</version>
</dependency>
<!-- springboot 集成包-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Constraint 详解

Bean validation
Constraint详细信息
@Null被注释的元素必须为 null
@NotNull被注释的元素不能为 null
@AssertTrue被注释的元素必须为 true
@AssertFalse被注释的元素必须为 false
@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size被注释的元素大小必须在指定的范围内
@Digits(integer,fraction)被注释的元素必须是一个小数,且整数的位数不能超过integer,小数部分的位数不能超过fraction
@Past被注释的元素必须是一个过去的日期
@Future被注释的元素必须是一个将来的日期
@Pattern(value)被注释的元素必须符合指定的正则表达式
Hibernate Validator 附加 constraint
Constraint详细信息
@Email被注释的元素必须是电子邮箱
@Length被注释的字符串的大小必须在指定范围内
@NotEmpty被注释的字符串非空
@Range(min=,max=,message=)被注释的元素必须在合适范围内
@NotBlank验证字符串非null,且长度必须大于0

Valid 和 Validated 的区别

  1. @Valid 可以用在方法,构造函数,方法参数和成员属性(字段)上
  2. @Validated 可以用在类型,方法和参数上,但是不能用在成员属性上
  3. @Valid 支持嵌套检测,@Validated 不支持嵌套检测
  4. @validated 提供分组功能,@Valid 没有分组功能
  5. @Valid 是使用Hibernate Validation 的时候使用
    说明:java的JSR303声明了@Valid这类接口,而Hibernate-validator对其进行了实现。
  6. @validated 是Spring Validation 校验机制使用,是 @Valid 的一次封装

组序列

默认情况下,不同组别的约束验证是无序的,然而在某些情况下,约束验证的顺序却很重要。
例:

  1. 第二个组中的约束验证依赖于一个稳定的状态来运行,而这个稳定的状态是由第一个组来进行验证的。
  2. 某个组的验证比较耗时,CPU和内存的使用率相对比较大,最优的选择是将其放在最后进行验证。因此,在进行组验证的时候尚需提供一种有序的验证方式,这就提出了组序列的概念。

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

代码实现

定义分组接口:

public interface FirstConstraintGroup {
}
public interface SecondConstraintGroup {
}
import javax.validation.GroupSequence;

@GroupSequence({FirstConstraintGroup.class,SecondConstraintGroup.class})
public interface Group {
}

实体类字段增加组序列:

    /**
     * 业务类型
     */
    @NotNull(groups={FirstConstraintGroup.class},message = "BTYPE 不能为空")
    @Size(groups={SecondConstraintGroup.class},max = 4, min = 4, message = "BTYPE 的长度不符合业务规定")
    String bType;

接口类增加组序列:

    @PostMapping("open")
    public Object openMonthCard(@RequestBody @Validated({Group.class}) InputJsonVo inputJsonVo) {
        OutputParams outputParams = cardAccountMonthService.openCardAccount(inputJsonVo, JSONUtil.toBean(inputJsonVo.getInputParamVo(), OpenCardInputVo.class));
        return Util.GenOutPutJson(outputParams, new OutputJsonVo(inputJsonVo.getbType(), inputJsonVo.getTradeNo()));
    }

自定义校验注解

代码实现

创建 Annotation:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * 自定义参数校验注解
 * 校验 List 集合中是否有null 元素
 */
@Target({ANNOTATION_TYPE, METHOD, FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = ListNotHasNullValidatorImpl.class)
public @interface ListNotHasNull {


    /**
     * 添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义
     */
    int value() default 0;

    String message() default "List集合中不能含有null元素";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

创建实现类: (需继承 ConstraintValidator<A extends Annotation, T> 接口)

import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;

@Component
public class ListNotHasNullValidatorImpl implements ConstraintValidator<ListNotHasNull, List> {

    private int value;

    @Override
    public void initialize(ListNotHasNull constraintAnnotation) {
        // 传入value 值,可以在校验中使用
        this.value = constraintAnnotation.value();
    }

    @Override
    public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) {
        for (Object object : list) {
            if (object == null) {
                // 如果List集合中含有Null元素,校验失败
                return false;
            }
        }
        return true;
    }
}

实体类的使用:

    /**
     * 测试modelList
     */
    @ListNotHasNull(message = "testModelList 中不能含有Null 元素")
    List<Long> testModelList;

基于Validation 注解 对于泛型类型不支持的解决办法

我们知道javax的@Valid 注解的效果是递归下去的,可以实现嵌套检测,但是如果实体类中使用了泛型,则Validation 注解就不生效了。因为javax的校验实现 ValidatorImpl.validate(T object, Class<?>... groups)(是hibernate包里的),读取的是最外层类型的编译时结构,而非运行时类型,所以泛型就失效了。

解决方案是在泛型类型的字段上面加上 @valid 注解。(jakarta.validation-api-2.0.2.jar 版本)

/** 搜索条件 */
    @Valid
    private T searchReq;

其他方案参考:
@Valid 无法校验List<E>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值