一.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;/*** 初始化操作*/@Beforepublic 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);}});}/*** 结果打印*/@Afterpublic void print() {set.forEach(item -> {//输出验证错误信息System.out.println(item.getMessage());});
// set1.forEach(item -> {
// //输出验证错误信息
// System.out.println(item.getMessage());
// });}@Testpublic void nullValidation() {//使用验证器对对象进行验证set = validator.validate(userInfo);}/*** 级联验证测试方法*/@Testpublic void graphValidation() {set = validator.validate(userInfo);}/*** 验证注册时,邮箱是否为空*/@Testpublic void groupValidation() {set = validator.validate(userInfo, UserInfo.RegisterGroup.class);}/*** 组排序*/@Testpublic void groupSequenceValidate() {set = validator.validate(userInfo, UserInfo.Group.class);}/*** 对方法输入参数进行约束注解校验*/@Testpublic 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);}/*** 对方法返回值进行约束校验*/@Testpublic 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);}/*** 对构造函数输入参数进行校验*/@Testpublic 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*/@Overridepublic 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;/*** 初始化操作*/@Beforepublic void init() {//初始化验证器validator = Validation.buildDefaultValidatorFactory().getValidator();//初始化待验证对象 用户信息userInfo = new UserInfo();userInfo.setPhone("15987377373");}/*** 结果打印*/@Afterpublic void print() {set.forEach(item -> {//输出验证错误信息System.out.println(item.getMessage());});}@Testpublic void nullValidation() {//使用验证器对对象进行验证set = validator.validate(userInfo);}}
结果: