Hibernate Validator参数校验

1,738 阅读4分钟

我又回来了,没错,还是因为太无聊了!

正文

我们都知道在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等(不校验这样是要被骂的,我渣以身试法,果然被骂了0.0),敲代码嗖嗖嗖的敲完了业务逻辑,但是如果参数传的有误,那么接口还是用不了的,我老大原来跟我讲过一句话,永远不要相信别人,只能信任自己,其实这句话真的没错,因为有些时候,有可能你没有及时更新接口文档,或者前端没有拿到最新的接口文档,或者有些参数,前端并没有做很精细的校验,那么都有可能会造成接口用不了,这样如果在生产环境发生了,那肯定是要被骂的!

今天要记录的是hibernate validator参数校验方式,提供了一套比较完善、便捷的验证实现方式,当然有优点就会有缺点,比如有些校验需要从数据库查询数据再进行校验,这种的就没法用Hibernate Validator校验了,好了,话不多说,直入主题吧:

Hibernate Validator的作用

  • 验证逻辑与业务逻辑之间进行了分离,降低了程序耦合度;

  • 统一且规范的验证方式,无需你再次编写重复的验证代码;

Hibernate Validator的使用

1、首先引入jar包(springboot项目就无需引入了,因为spring-boot-starter-web包里面有hibernate-validator包)

<dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.9.Final</version>
</dependency>

2、看下Hibernate Validator常用的注解

注解 释义
@Null 必须为null
@NotNull 不能为null
@AssertTrue 必须为true
@AssertFalse 必须为false
@Min 必须为数字,其值大于或等于指定的最小值
@Max 必须为数字,其值小于或等于指定的最大值
@DecimalMin 必须为数字,其值大于或等于指定的最小值
@DecimalMax 必须为数字,其值小于或等于指定的最大值
@Size 集合的长度
@Digits 必须为数字,其值必须再可接受的范围内
@Past 必须是过去的日期
@Future 必须是将来的日期
@Pattern 必须符合正则表达式
@Email 必须是邮箱格式
@Length 长度范围
@NotEmpty 不能为null,长度大于0
@Range 元素的大小范围
@NotBlank 不能为null,字符串长度大于0(限字符串)

3、给Java对象添加注解校验

    /**
     * 姓名
     */
    @NotNull(message = "姓名不能为null")
    private String name;

    /**
     * 年龄
     */
    @Max(value = 20, message = "年龄不能大于20岁")
    private String age;

    /**
     * 国籍
     */
    @Null(message = "国籍必须为null")
    private String nationality;

4、POST接口验证(BindingResult:验证不通过的结果集合,@Valid:验证注解是否符合要求,通俗一点讲,就是要指明哪些参数需要校验、并且校验这些参数是否满足相应的规则)

    @PostMapping("hibernate/validator/test")
    public void test1(@RequestBody @Valid User user, BindingResult result){
        if(result.hasErrors()){
            for (ObjectError error : result.getAllErrors()) {
                System.out.println(error.getDefaultMessage());
            }
        }
    }

5、调用接口,查看返回内容

这里要注意,name字段判断的是不能为null,但如果传的是空字符串的话,是不会提示的!

自定义注解

1、创建自定义注解,判断性格

package com.hibernate.validator.Model;

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

/**
 * @author wx
 */
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CharacterConstraintValidator.class)
public @interface Character {

    String message() default "性格不能为易暴怒,打不过";

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

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

@Target:说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标,取值有以下几种:

@Retention:定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中,如下:

@Constraint:代表处理逻辑的是CharacterConstraintValidator类(新定义的注解都需要校验什么内容,都是在这个类中判断的)

2、创建逻辑类

package com.hibernate.validator.Model;

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

/**
 * @author wx
 */
public class CharacterConstraintValidator implements ConstraintValidator<Character, String> {

    @Override
    public void initialize(Character constraintAnnotation) {
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        return value != null && (value.equals("温和") || value.equals("特别温和"));
    }
}

3、实体类添加新注解

    /**
     * 姓名
     */
    @NotNull(message = "姓名不能为空")
    private String name;

    /**
     * 年龄
     */
    @Max(value = 20, message = "年龄不能大于20岁")
    private String age;

    /**
     * 国籍
     */
    @Null(message = "国籍必须为null")
    private String nationality;

    /**
     * 性格
     */
    @Character
    private String character;

4、调用接口,查看结果

大家写代码一定要注意规范,可以在idea上安装一个阿里规约插件,帮助您时刻修正不规范的写法,还有,多写注释,这是本职工作,别给后来者留坑,祝愿大家越来越好

如果有需要的话可以关注一下我的公众号,会即时更新Java相关技术文章,公众号内还有一些实用资料,如Java秒杀系统视频教程、黑马2019的教学资料(IDEA版)、BAT面试题汇总(分类齐全)、MAC电脑常用安装包(有一些是淘宝买的,已PJ的)。

结束,睡觉,晚安!