一.bean validation和hibernate validator参数校验常用约束注解:
空值校验类:@Null,@NotNull,@NotEmpty,@NotBlank等
 范围校验类:@Min,@Size,@Digits,@Future,@Negative等
 其它校验类:@Email,@URL,@AssertTrue,@Pattern等
二.初级约束注解:
1. @NotNull(message = “用户id不能为空”)
- 没有设置值时会返回
- 设置为userInfo.setUserId(“”);时不会返回
- userInfo.setUserId(" ");时不会返回
2.@NotEmpty(message = “用户名不能为空”)
- 不会自动去掉字符串前后的空格再判断是否为空
- 没有设置值时会返回
- userInfo.setUserName(“”);时返回
- userInfo.setUserName(" ");时不返回
3.@NotBlank(message = “密码不能为空”)
- 自动去掉字符串前后的空格再判断是否为空
- 没有设置值时会返回
- userInfo.setPassWord(“”);时返回
- userInfo.setPassWord(" ");时返回
4.@Length(min = 6,max = 20,message = “密码不能少于6位,也不能多于20位”)
- 即数量必须在6到20之间(包含6和20)
5.@Email(message = “邮箱不正确”)
- 可以直接不设置值
- 必须是正确的邮箱格式
6. @Min(value = 18, message = “年龄不能小于18岁”)
- 可以直接不设置值
- 即年龄必须大于或者等于18岁
7. @Max(value = 60, message = “年龄不能大于60岁”)
- 可以直接不设置值
- 即年龄必须等于小于60岁
8.@Past(message = “生日只能是过去的时间或者现在的时间”)
- 可以直接不设置值
- 传来的时间只能是过去的时间或者现在的时间,不能是未来时间
9.@Size(min = 1,message = “不能少于一个好友”)
- 可以直接不设置值
- 集合里面的内容不能少于1
三.中级约束注解:
1.@Valid
- private List<@Valid UserInfo> friends;表示对UserInfo类中里面的每个属性进行验证
2.@NotNull(message = “注册时邮箱不能为空”,groups = RegisterGroup.class)
-  //注册场景 public interface RegisterGroup{}
 //登录场景 public interface LoginGroup{}
- 注册时邮箱不能为空,登录时可以为空
- set = validator.validate(userInfo,UserInfo.RegisterGroup.class);
3.//组排序场景
 @GroupSequence({
 LoginGroup.class,
 RegisterGroup.class,
 Default.class
 })
 public interface Group{}
- set = validator.validate(userInfo,UserInfo.Group.class);
- 先验证 LoginGroup组的,都通过才验证下面的,不通过直接返回验证错误信息,验证顺序按照上面的顺序进行验证
四.高级约束注解:
1.public void setUserInfo(@Valid UserInfo userInfo){ }
 set1 = executableValidator.validateParameters(service,method1,paramObject);
- @Valid对方法输入参数进行约束注解校验
2.public @Valid UserInfo getUserInfo(){return new UserInfo();}
 set1 = executableValidator.validateReturnValue(userInfoService,method,returnValue);
- @Valid对方法返回值进行约束校验
3.public UserInfoService(@Valid UserInfo userInfo){}
 set1 = executableValidator.validateConstructorParameters(constructor,paramObject);
- @Valid对构造函数输入参数进行校验
五.上面初,中,高级注解示例:
pom.xml
<!-- Validation 相关依赖 -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.16.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.6</version>
        </dependency>
待验证对象实体类UserInfo.java:
package com.mystudy.elastic.job.springboot.validation;
import org.hibernate.validator.constraints.Length;
import javax.validation.GroupSequence;
import javax.validation.Valid;
import javax.validation.constraints.*;
import javax.validation.groups.Default;
import java.util.Date;
import java.util.List;
/**
 * 待验证对象实体类
 * 用户信息类
 */
public class UserInfo {
    //登录场景
    public interface LoginGroup{}
    //注册场景
    public interface RegisterGroup{}
    //组排序场景
    @GroupSequence({
            LoginGroup.class,
            RegisterGroup.class,
            Default.class
    })
    public interface Group{}
    /**
     * 用户id
     */
    @NotNull(message = "用户id不能为空")
    private String userId;
    /**
     * 用户名
     */
    @NotEmpty(message = "用户名不能为空")
    private String userName;
    /**
     * 密码
     */
    @NotBlank(message = "密码不能为空")
    @Length(min = 6, max = 20, message = "密码不能少于6位,也不能多于20位")
    private String passWord;
    /**
     * 邮箱
     */
//    @NotNull(message = "注册时邮箱不能为空",groups = RegisterGroup.class)
    @Email(message = "邮箱不正确")
    private String email;
    /**
     * 年龄
     */
    @Min(value = 18, message = "年龄不能小于18岁")
    @Max(value = 60, message = "年龄不能大于60岁")
    private Integer age;
    /**
     * 手机号
     */
    @Phone(message = "手机号不是158后面随便的手机号")
    private String phone;
    /**
     * 生日
     */
    @Past(message = "生日只能是过去的时间或者现在的时间")
    private Date birthday;
    /**
     * 好友列表
     */
    @Size(min = 1,message = "不能少于一个好友")
    private List<@Valid UserInfo> friends;
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassWord() {
        return passWord;
    }
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public List<UserInfo> getFriends() {
        return friends;
    }
    public void setFriends(List<UserInfo> friends) {
        this.friends = friends;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}
用户信息服务类UserInfoService.java:
package com.mystudy.elastic.job.springboot.validation;
import javax.validation.Valid;
/**
 * 用户信息服务类
 */
public class UserInfoService {
    /**
     *  userInfo作为输入参数
     * @param userInfo
     */
    public void setUserInfo(@Valid UserInfo userInfo){
    }
    /**
     * userInfo作为输出参数
     * @return
     */
    public @Valid UserInfo getUserInfo(){
        return new UserInfo();
    }
    /**
     * 默认构造函数
     */
    public UserInfoService(){
    }
    /**
     * 接收userInfo作为参数的构造函数
     * @param userInfo
     */
    public UserInfoService(@Valid UserInfo userInfo){
    }
}
验证测试类ValidationTest.java:
package com.mystudy.elastic.job.springboot.validation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
/**
 * 验证测试类
 */
public class ValidationTest {
    //验证器对象
    private Validator validator;
    //待验证对象
    private UserInfo userInfo;
    //验证结果集合
    private Set<ConstraintViolation<UserInfo>> set;
    //验证结果集合
    private Set<ConstraintViolation<UserInfoService>> set1;
    /**
     * 初始化操作
     */
    @Before
    public void init() {
        //初始化验证器
        validator = Validation.buildDefaultValidatorFactory().getValidator();
        //初始化待验证对象 用户信息
        userInfo = new UserInfo();
        userInfo.setUserId(" ");
        userInfo.setUserName("  ");
        userInfo.setPassWord("  ");
        userInfo.setPassWord("333333");
        userInfo.setAge(18);
        userInfo.setBirthday(new Date());
        userInfo.setPhone("15987377373");
        UserInfo friend = new UserInfo();
        friend.setUserId("wangxiaoxi");
        friend.setUserName("王小喜");
        friend.setPassWord("wangxiaoxi");
        userInfo.setFriends(new ArrayList() {{
            add(friend);
        }});
    }
    /**
     * 结果打印
     */
    @After
    public void print() {
        set.forEach(item -> {
            //输出验证错误信息
            System.out.println(item.getMessage());
        });
//        set1.forEach(item -> {
//            //输出验证错误信息
//            System.out.println(item.getMessage());
//        });
    }
    @Test
    public void nullValidation() {
        //使用验证器对对象进行验证
        set = validator.validate(userInfo);
    }
    /**
     * 级联验证测试方法
     */
    @Test
    public void graphValidation() {
        set = validator.validate(userInfo);
    }
    /**
     * 验证注册时,邮箱是否为空
     */
    @Test
    public void groupValidation() {
        set = validator.validate(userInfo, UserInfo.RegisterGroup.class);
    }
    /**
     * 组排序
     */
    @Test
    public void groupSequenceValidate() {
        set = validator.validate(userInfo, UserInfo.Group.class);
    }
    /**
     * 对方法输入参数进行约束注解校验
     */
    @Test
    public void paramValidation() throws NoSuchMethodException {
        //获取校验执行器
        ExecutableValidator executableValidator = validator.forExecutables();
        //待验证对象
        UserInfoService service = new UserInfoService();
        //待验证方法
        Method method1 = service.getClass().getMethod("setUserInfo", UserInfo.class);
        //方法的输入参数
        Object[] paramObject = new Object[]{new UserInfo()};
        //对方法的输入参数进行校验
        set1 = executableValidator.validateParameters(service, method1, paramObject);
    }
    /**
     * 对方法返回值进行约束校验
     */
    @Test
    public void returnValueValidation() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //获取校验执行器
        ExecutableValidator executableValidator = validator.forExecutables();
        //构造要验证的方法对象
        UserInfoService userInfoService = new UserInfoService();
        Method method = userInfoService.getClass().getMethod("getUserInfo");
        //调用方法得到返回值
        Object returnValue = method.invoke(userInfoService);
        //校验方法返回值是否符合约束
        set1 = executableValidator.validateReturnValue(userInfoService, method, returnValue);
    }
    /**
     * 对构造函数输入参数进行校验
     */
    @Test
    public void constructorValidation() throws NoSuchMethodException {
        //获取验证执行器
        ExecutableValidator executableValidator = validator.forExecutables();
        //获取构造函数
        Constructor<UserInfoService> constructor = UserInfoService.class.getConstructor(UserInfo.class);
        Object[] paramObject = new Object[]{new UserInfo()};
        //校验构造函数
        set1 = executableValidator.validateConstructorParameters(constructor, paramObject);
    }
}
六.自定义注解:
自定义手机号注解@interface Phone:
package com.mystudy.elastic.job.springboot.validation;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
 * 自定义手机号注解
 */
@Documented
//注解的作用目标(可以设置作用在类,方法等等)
@Target({ElementType.FIELD})
//注解的保留策略(注解的生命周期)
@Retention(RetentionPolicy.RUNTIME)
//不同之处:与注解关联的验证器
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {
    //注解验证不通过时输出的信息
    String message() default "手机号验证错误";
    //约束注解在验证时所属的组别
    Class<?>[] groups() default {};
    //约束注解的有效负载
    Class<? extends Payload>[] payload() default {};
}
自定义手机号注解关联的验证器class PhoneValidator implements ConstraintValidator<Phone, String>:
package com.mystudy.elastic.job.springboot.validation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 自定义手机号注解关联的验证器
 */
public class PhoneValidator implements ConstraintValidator<Phone, String> {
    /**
     * 自定义校验逻辑方法
     *
     * @param s
     * @param constraintValidatorContext
     * @return
     */
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        //手机号验证规则:158后面随便
        String check = "158\\d{8}";
        Pattern regex = Pattern.compile(check);
        String phone = Optional.ofNullable(s).orElse("");
        Matcher matcher = regex.matcher(phone);
        //返回是否匹配
        return matcher.matches();
    }
}
待验证对象实体类UserInfo:
package com.mystudy.elastic.job.springboot.validation;
/**
 * 待验证对象实体类
 * 用户信息类
 */
public class UserInfo {
    /**
     * 手机号
     */
    @Phone(message = "手机号不是158后面随便的手机号")
    private String phone;
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
}
验证测试类ValidationTest
package com.mystudy.elastic.job.springboot.validation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
/**
 * 验证测试类
 */
public class ValidationTest {
    //验证器对象
    private Validator validator;
    //待验证对象
    private UserInfo userInfo;
    //验证结果集合
    private Set<ConstraintViolation<UserInfo>> set;
    /**
     * 初始化操作
     */
    @Before
    public void init() {
        //初始化验证器
        validator = Validation.buildDefaultValidatorFactory().getValidator();
        //初始化待验证对象 用户信息
        userInfo = new UserInfo();
        userInfo.setPhone("15987377373");
    }
    /**
     * 结果打印
     */
    @After
    public void print() {
        set.forEach(item -> {
            //输出验证错误信息
            System.out.println(item.getMessage());
        });
    }
    @Test
    public void nullValidation() {
        //使用验证器对对象进行验证
        set = validator.validate(userInfo);
    }
}
结果:
 









![[java聊天室]服务器发送消息给客户端守护线程同步锁(三)](https://img-blog.csdnimg.cn/1a48c92bb29b438096f5174b9078882f.png)








