前言
我们在java项目开发中(典型场景为springmvc项目的controller参数接收)都需要对参数合法性(非空性,范围,格式等)进行校验,最简单的写法是使用if...else进行逐个判断,但是此类开发工作繁琐,代码不够优雅,这里我们可以使用jsr-303中的一项子规范Bean Validation来处理,其中Hibernate Validator 是 Bean Validation 的参考实现,本次演示便是对Hibernate Validator的使用和扩展,千言万语不如代码一篇!
正文
环境关键词:idea、maven、springboot、hibernate-validator
一、代码清单Example.java 自定义扩展校验注解及Hibernate Validator标准注解使用示例类
InEnumValues.java 自定义扩展校验注解类
InEnumValuesValidatorImpl.java 自定义扩展校验实现类
ValidateUtil.java 核心校验工具类
二、具体实现package cn.seally.collector.validator;
import cn.seally.collector.common.ApiException;
import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.*;
public class ValidateUtil {
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static String validate(T t,String... fields) throws ApiException {
if (null == t) {
return "校验对象为空";
}
List errorList = new ArrayList<>();
Set> constraintViolations = new HashSet<>();
boolean checkALL = true;
if(null != fields && fields.length > 0){
for(String field: fields){
if(null != field && !field.trim().isEmpty()){
checkALL = false;
constraintViolations.addAll(validator.validateProperty(t,field));
}
}
}
if(checkALL){
constraintViolations = validator.validate(t);
}
for (ConstraintViolation constraintViolation : constraintViolations) {
errorList.add("["+constraintViolation.getPropertyPath()+"]"+constraintViolation.getMessage());
}
if ((null != errorList) && !errorList.isEmpty()) {
return StringUtils.join(errorList, ";");
}
return null;
}
}
package cn.seally.collector.validator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@documented
@Constraint(validatedBy = InEnumValuesValidatorImpl.class)//此处指定了注解的实现类为InEnumValuesValidatorImpl
public @interface InEnumValues {
int[] intEnums() default {};
String[] strEnums() default {};
String message() default "不在指定枚举值范围";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@documented
@interface List {
InEnumValues[] value();
}
}
package cn.seally.collector.validator; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.HashSet; import java.util.Set; public class InEnumValuesValidatorImpl implements ConstraintValidator{ Set values = new HashSet<>();//这里我本意是想要校验基础常用类型比如整型和字符串行的枚举值,但是整型和字符串型都可以转为字符串统一判断,因此定义一个字符串型的Set 来盛装注解中的intEnums和strEnums中获取到的校验比对范围 @Override public void initialize(InEnumValues constraintAnnotation) { if(null != constraintAnnotation.intEnums()){ for(int i : constraintAnnotation.intEnums()){ values.add(i+""); } } if(null != constraintAnnotation.strEnums()){ for(String i : constraintAnnotation.strEnums()){ values.add(i); } } } @Override public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) { //如果校验值是null认为校验通过,因为有专门的非null校验注解去做非null的校验 if(null == object){ return true; } //如果该注解包含需要校验的 if(null != values && !values.isEmpty()){ return values.contains(object.toString()); } return true; } }
package cn.seally.collector.validator;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
public class Example {
@NotNull
private String name;
@NotEmpty
private String gender;
@AssertTrue
@NotNull
private Boolean woman;
@Pattern(regexp="^1\d{10}$")
@NotNull
private String telephone;
@Min(1)
@Max(100)
@NotNull
private Integer age;
@Size(min = 1,max = 2)
private String address;
@Digits(integer = 3,fraction = 2)
@NotNull
private Double weight;
private Long foot;
private Date birth;
@DecimalMin("0.00")
@DecimalMax("2.00")
@NotNull
private BigDecimal money;
private Float salary;
@InEnumValues(strEnums = {"ellie","dennis"})
@NotNull
private String friend;
@InEnumValues(intEnums = {1,2,3})
private Integer level;
@NotEmpty
@Size(min=1,max = 2,message = "个数超出期望值范围")
private List hobbies;
private Set friends;
public static void main(String[] args) {
Example param = new Example();
param.setWoman(false);
param.setAddress("你好么");
param.setMoney(new BigDecimal("-12.0"));
ArrayList hobbies = new ArrayList<>();hobbies.add("打球");hobbies.add("看书");hobbies.add("看电影");
param.setHobbies(hobbies);
param.setWeight(Double.valueOf(123.234D));
param.setTelephone("130");
param.setFriend("dnc");
param.setLevel(4);
System.out.println("param校验所有属性结果为:n"+ValidateUtil.validate(param));
System.out.println("param校验指定属性结果为:n"+ValidateUtil.validate(param,"name"));
}
public String getFriend() {
return friend;
}
public void setFriend(String friend) {
this.friend = friend;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Boolean getWoman() {
return woman;
}
public void setWoman(Boolean woman) {
this.woman = woman;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public Long getFoot() {
return foot;
}
public void setFoot(Long foot) {
this.foot = foot;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
public Float getSalary() {
return salary;
}
public void setSalary(Float salary) {
this.salary = salary;
}
public List getHobbies() {
return hobbies;
}
public void setHobbies(List hobbies) {
this.hobbies = hobbies;
}
public Set getFriends() {
return friends;
}
public void setFriends(Set friends) {
this.friends = friends;
}
} 


