一文了解Javax中的valid框架

  spring开发web项目,都会需要对入参的长度,格式等进行校验,如果将这些都写在代码中,那么代码就会很不美观.validate框架能很好的解决这些和业务无关的校验.

  1. 准备.

  需要使用valid的框架,需要在项目中引入依赖

    // valid 校验框架
    implementation group: 'javax.validation', name: 'validation-api', version: '2.0.1.Final'
    implementation group: 'org.hibernate', name: 'hibernate-validator', version: '7.0.1.Final'

首先需要解释下为什么需要这2个依赖.

javax.validation的依赖中包含了平常发开中经常使用的注解校验.

@Null 限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@Past 验证注解的元素值(日期类型)比当前时间早
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式  

 这些注释相关的校验却是写在validator中的

 

 

 也就是说javax中的validation定义了相关的校验注解和 ConstraintValidator 接口, hibernate则通过实现这个接口来对每一个注解进行校验

 

了解了相关的工作原理,我们就能很好的模仿它进行相应的开发,比如枚举类的校验.

1. 第一步,先定义需要校验的注解

package com.xdj.robot.annotation;

import com.xdj.robot.valid.EnumValidator;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValidator.class)  // 这里必须写上自己编写的validator 不然会抛出找不到校验器的错误
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
public @interface EnumValid {


    String message() default "";

    // 作用参考@Validated和@Valid的区别
    Class<?>[] groups() default {};

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

    /**
     * 目标枚举类
     */
    Class<? extends Enum> value();

    /**
     * 是否忽略空值
     */
    boolean ignoreEmpty() default true;

}

 

 2.编写自己的校验器

package com.xdj.robot.valid;

import com.xdj.robot.annotation.EnumValid;
import com.xdj.robot.enums.SexEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;


@Slf4j
@Component
public class EnumValidator implements ConstraintValidator<EnumValid, Enum> {


    private EnumValid annotation;

    @Override
    public void initialize(EnumValid constraintAnnotation) {
        annotation = constraintAnnotation;
    }

    @Override
    public boolean isValid(Enum t, ConstraintValidatorContext constraintValidatorContext) {

        boolean result = false;

        Class<?> cls = annotation.value();

        boolean ignoreEmpty = annotation.ignoreEmpty();
        if (!ignoreEmpty || (cls.isEnum() && t != null)) {

            Object[] objects = cls.getEnumConstants();
            for (Object obj : objects) {
                // 使用此注解的枚举类需要重写toString方法,改为需要验证的值
                if (obj.toString().equals(String.valueOf(t))) {
                    result = true;
                    break;
                }
            }
        }else result = true;
        return result;
    }
}

 

 3.定义枚举类型和需要校验的实体

package com.xdj.robot.enums;

public enum  SexEnum {
    FEMALE, MALE;
}


package com.xdj.robot.dto;

import com.xdj.robot.annotation.EnumValid;
import com.xdj.robot.enums.SexEnum;
import lombok.Data;

import javax.validation.constraints.NotEmpty;
import java.math.BigDecimal;

@Data
public class ValidTableDTO {

    @NotEmpty(message = "名称不能为空")
    private String nme;

    @EnumValid(value = SexEnum.class, message = "性别必须为FEMALE, MALE ")
    private SexEnum sex;

    private BigDecimal money;

    private String phone;

}

 

 4.最后进行校验 验证

{
    "code": 9999,
    "message": "性别必须为FEMALE, MALE ",
    "data": null
}

 

posted @ 2021-09-20 16:48  主宰-  阅读(783)  评论(0编辑  收藏  举报