化繁为简,使用Hibernate Validator实现参数校验(二)

目录

引言

集合校验

普通集合

自定义对象的集合

级联校验

快速失败

自定义校验


引言

接一篇文章化繁为简,使用Hibernate Validator实现参数校验(一)_往事如烟隔多年的博客-CSDN博客,本文继续对参数校验相关知识作以延伸。

集合校验

普通集合

当集合中存放的元素为包装类型时,采用如下方式进行校验。

校验方法

ResultDataVO createUserConsumption(@RequestBody
    							   @NotEmpty(message="id列表不能为空")
    							   List idList){
        return ResultDataVO.success();
}

自定义对象的集合

 若此时接口需要批量传入用户信息,为了满足该条件创建如下的DTO对象,注意当前对象包含了分组校验信息,此时需要注意要验证集合对象时,必须使用@Valid注解,同时分组校验将失效。

UserDTO

public class UserDTO{
    @NotNull(message = "id不能为空",groups = {UpdateGroup.class})
    private Integer id;
    
    @NotBlank(message = "名称不能为空",groups = {AddGroup.class,UpdateGroup.class,Default.class})
    private String name;
    
    @NotNull(message = "默认值不能为空")
    private Integer defaultValue;
}

校验方法

ResultDataVO createUserConsumption(@RequestBody
    							   @NotEmpty(message="参数列表不能为空")
    							   @Valid List userList){
        return ResultDataVO.success();
}

级联校验

在上一步的集合校验中,若使用了@RequestBody + @Validated注解想对集合中元素进行分组校验时,会发现基础校验都将失效,而使用@Valid注解虽然解决了校验失效问题,但又无法满足分组校验的需求,那么有什么办法可以解决这个问题呢?有以下两种方案:

1.将DTO拆分,不同的DTO对应不同的数据操作(增删改查),沿用上面的方法完成校验。

2.创建新的DTO类,在类中使用集合存自定义数据,外部可以继续使用分组校验。

这里以方案二作演示,新建UserDataDTO类,其中包含一个集合对象,存储我们的UserDTO对象,需要在该字段上添加@Valid注解,除集合外,其它嵌套类型的对象需要验证时也可添加该注解,此处添加@Valid注解后,对应参数中包含基础校验注解时,将进行校验。

UserDataDTO

public class UserDataDTO{
    @Valid
    @NotEmpty(message="用户信息列表不能为空")
    private List userDataList;
}

校验方法

此处可以在@Validated中指定分组校验的组信息。

@PostMapping("/validationInfo")
public ResultDataVO userListValidation(@RequestBody 
                                       @Validated(AddGroup.class)
                                       @NotNull(message = "用户数据不能为空") 
                                       UserDataDTO userDataDTO){

        return ResultDataVO.success();
}

请求参数

此处需要特别注意:使用JSON传入请求参数时,需要传入的对象信息名称为 userDataList,而不是当前入参userDataDTO!

{
    "userDataList":[
        {
            "id":"1",
            "name":"123"
        }
    ]
}

快速失败

默认情况下Validator校验框架会对所有的入参进行校验,而当请求中参数越来越多,某些参数的校验异常耗时,将会导致接口响应速度变慢,因此可以通过配置快速失败的方式,实现当一个参数校验不通过时立即返回,不会继续后面的校验。

创建配置类,设置failFast属性为true即可。

@Configuration
public class ValidationConfiguration {
    @Bean
    public Validator validator(AutowireCapableBeanFactory springFactory) {
        try (ValidatorFactory factory = Validation.byProvider(HibernateValidator.class)
                .configure()
                // 快速失败
                .failFast(true)
                // 解决 SpringBoot 依赖注入问题
                .constraintValidatorFactory(new SpringConstraintValidatorFactory(springFactory))
                .buildValidatorFactory()) {
            return factory.getValidator();
        }
    }
}

自定义校验

目前项目中对于手机号格式校验使用了@Pattern注解,通过正则表达式实现,而当校验需求增多时,需要不断CV代码,而原生的Validator中并没有提供手机号校验,因此可以通过自定义注解来实现手机号格式校验。

首先创建一个注解类型Phone,用于指定解作用的范围,实现类等基本信息

自定义注解@Phone 

/*
 * @Retention 指定注解保留的时期
 * @Target 注解可作用的范围
 * @Constraint 与注解关联的实现类
 */
@Documented
@Target({FIELD,PARAMETER})
@Retention(RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {

    // 约束注解验证时的输出信息,默认为空
    String message() default "手机号校验错误";

    // 约束注解在验证时所属的组别
    Class[] groups() default {};

    // 约束注解的有效负载
    Class[] payload() default {};

    
}

实现类PhoneValidator

在与自定义注解关联的类中需要实现ConstraintValidator接口,并重写其isValid方法,可在方法内部编写具体的业务验证逻辑。

public class PhoneValidator
        implements ConstraintValidator {

    /**
     * 自定义校验逻辑方法
     * @param value
     * @param context
     * @return
     */
    @Override
    public boolean isValid(String value,
                           ConstraintValidatorContext context) {

         // 手机号验证规则
        String check = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$";
        Pattern regex = Pattern.compile(check);
        // 空值处理
        String phone = Optional.ofNullable(value).orElse("");
        Matcher matcher = regex.matcher(phone);
        // 返回验证结果
        return matcher.matches();
    }
}

使用

与基础校验注解使用方法一致,在需要校验的字段上添加注解即可。

@Phone(message = "手机号格式不正确")
private String phoneNumber;

你可能感兴趣的:(java,开发语言,spring,boot,Validation,参数校验)