在工作中不可避免的要面对很多参数校验, 比如写新接口时需要对传入VO的必要字段进行校验, String 是否为空, Integer 最小值, 对象是否为null, 等等.
而使用 hibernate的validator工具对参数进行校验, 可以极大的简化流程, 当然不可避免的就是需要在被校验字段上加上注解信息.

1. 相关依赖
<!-- 参数校验工具 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>el-impl</artifactId>
<version>2.2</version>
</dependency>
2. ValidationUtil

对加上相关注解字段进行校验, 使用到 ValidationUtil.javaValidationResult.java两个文件, 也可在工具中直接抛出异常.

ValidationUtil 内容如下:

package com.liuzhihang.tool.validate;

import org.apache.commons.collections.CollectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.Set;

/**
* 对添加 hibernate.validator 注解的字段进行校验
*
* 使用前 需要引入 hibernate-validator 依赖
*
* @author liuzhihang
* @date 2017/11/22 11:08
*/
public class ValidationUtil {

private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

/**
* 会 验证 所有字段
*
* @param obj
* @param <T>
* @return 返回所有不符合的信息
*/
public static <T> ValidationResult validateAllField(T obj) {
ValidationResult result = new ValidationResult(true);
StringBuilder errorMsg = new StringBuilder();
if (obj == null) {
result.setHasPass(false);
result.setErrorMsg("The class is null!");
return result;
}

Set<ConstraintViolation<T>> violationSet = validator.validate(obj);
if (CollectionUtils.isNotEmpty(violationSet)) {
for (ConstraintViolation<T> violation : violationSet) {
errorMsg.append(violation.getMessage());
}
result.setHasPass(false);
result.setErrorMsg(errorMsg.toString());
}

return result;
}

/**
* 验证指定字段 是否符合信息
*
* @param obj
* @param fieldName
* @param <T>
* @return
*/
public static <T> ValidationResult validateOneField(T obj, String fieldName) {
ValidationResult result = new ValidationResult(true);
if (obj == null) {
result.setHasPass(false);
result.setErrorMsg("The class is null!");
return result;
}
Set<ConstraintViolation<T>> violationSet = validator.validateProperty(obj, fieldName);
if (CollectionUtils.isNotEmpty(violationSet)) {
for (ConstraintViolation<T> violation : violationSet) {
result.setHasPass(false);
result.setErrorMsg(violation.getMessage());
}
}
return result;
}

/**
* 验证 所有字段, 当第一个不符合时 则直接返回信息
*
* @param obj
* @param <T>
* @return
*/
public static <T> ValidationResult validateAllFieldForOneBack(T obj) {
ValidationResult result = new ValidationResult(true);
if (obj == null) {
result.setHasPass(false);
result.setErrorMsg("The class is null!");
return result;
}

try {
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
result = validateOneField(obj, propertyDescriptor.getName());
if (result.getHasPass()) {
return result;
}
}

} catch (IntrospectionException e) {
result.setHasPass(false);
result.setErrorMsg("This validate has error : " + e);
}
return result;
}
}

ValidationResult 内容如下:

package com.liuzhihang.tool.validate;

/**
* @Description:
* @Author: liuzhihang
* @Date: 2018/1/6 17:57
*/
public class ValidationResult {

private Boolean hasPass;

private String errorMsg;

public ValidationResult(Boolean hasPass) {
this.hasPass = hasPass;
}

public Boolean getHasPass() {
return hasPass;
}

public void setHasPass(Boolean hasPass) {
this.hasPass = hasPass;
}

public String getErrorMsg() {
return errorMsg;
}

public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}

@Override
public String toString() {
return "ValidationResult{" +
"hasPass=" + hasPass +
", errorMsg='" + errorMsg + '\'' +
'}';
}
}

3. 常用注解
Bean Validation 中内置的 constraint
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式

Hibernate Validator 附加的 constraint
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
4 测试示例

代码:

package com.liuzhihang.tool.validate;

import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

/**
* @author liuzhihang
* @date 2017/11/22 18:25
*/
@Data
public class ValidationVo {

@NotBlank(message = "The name must notEmpty!")
private String name;

@NotNull(message = "The age must notNull!")
@Min(value = 1, message = "The age must greater than 0!")
private Integer age;


public static void main(String[] args) {
ValidationVo validationVo = new ValidationVo();
System.out.println(ValidationUtil.validateAllField(validationVo).toString());
validationVo.setAge(1);
System.out.println(ValidationUtil.validateAllField(validationVo).toString());
validationVo.setName("二蛋");
System.out.println(ValidationUtil.validateAllField(validationVo).toString());
}
}


输出结果:

ValidationResult{hasPass=false, errorMsg='The name must notEmpty!The age must notNull!'}
ValidationResult{hasPass=false, errorMsg='The name must notEmpty!'}
ValidationResult{hasPass=true, errorMsg='null'}