com.zcj.util.validator.ValidatorBuilder Maven / Gradle / Ivy
package com.zcj.util.validator;
import com.zcj.util.UtilClass;
import com.zcj.util.UtilDate;
import com.zcj.util.UtilRegex;
import com.zcj.util.UtilString;
import com.zcj.util.validator.annotation.Validator;
import com.zcj.util.validator.constant.StrFormat;
import com.zcj.util.validator.dto.ValidatorResult;
import com.zcj.web.spring.SpringBeanUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
/**
* 实体中属性的格式验证工具
*
* @author [email protected]
* @since 2019/10/14
*/
public class ValidatorBuilder {
private static final Logger logger = LoggerFactory.getLogger(ValidatorBuilder.class);
private static final String CN_NAME_ANNOTATION_CLASS = "com.zcj.util.coder.annotation.CnName";
private static final String API_MODEL_PROPERTY = "io.swagger.annotations.ApiModelProperty";
private final T object;
private final boolean includeAllField;
private final boolean includeEmptyTagField;
private final Set includeTagsField;
private final boolean oneErrorBreak;
private ValidatorBuilder(Builder builder) {
object = builder.object;
includeAllField = builder.includeAllField;
includeEmptyTagField = builder.includeEmptyTagField;
includeTagsField = builder.includeTagsField;
oneErrorBreak = builder.oneErrorBreak;
}
public ValidatorResult valid() {
ValidatorResult result = new ValidatorResult();
List fields = UtilClass.getAllFields(object.getClass());
for (Field field : fields) {
Validator[] validators = field.getAnnotationsByType(Validator.class);
if (validators != null && validators.length > 0) {
validOneField(field, validators, result);
if (oneErrorBreak && result.isFails()) {
break;
}
}
}
return result;
}
public static class Builder {
private T object = null;
private boolean includeAllField = false;
private boolean includeEmptyTagField = false;
private Set includeTagsField = new HashSet<>();
private boolean oneErrorBreak = false;
public Builder(T object) {
this.object = object;
}
/**
* 如果有一个属性验证不通过,马上返回
*
* @return com.zcj.util.validator.ValidatorUtil.Builder
*/
public Builder oneErrorBreak() {
this.oneErrorBreak = true;
return this;
}
/**
* 验证所有加了注解的字段
*
* @return com.zcj.util.validator.ValidatorUtil.Builder
*/
public Builder includeAllField() {
this.includeAllField = true;
return this;
}
/**
* 验证未设置 tags 的字段
*
* @return com.zcj.util.validator.ValidatorUtil.Builder
*/
public Builder includeEmptyTagField() {
this.includeEmptyTagField = true;
return this;
}
// 验证指定 tags 的字段
public Builder includeTagsField(String... tags) {
if (tags != null && tags.length > 0) {
for (String tag : tags) {
if (UtilString.isNotBlank(tag)) {
this.includeTagsField.add(tag);
}
}
}
return this;
}
public ValidatorBuilder build() {
return new ValidatorBuilder(this);
}
}
private void validOneField(Field field, Validator[] validators, ValidatorResult result) {
for (Validator validator : validators) {
if (needValid(validator.tags())) {
String fieldName = field.getName();
String fieldCnName = getFieldShowName(field, validator.chineseName());
Object fieldValue = null;
try {
field.setAccessible(true);
fieldValue = field.get(object);
} catch (IllegalAccessException e) {
logger.warn("验证[{}]属性时出错:获取属性值错误(已跳过验证)", field.getName());
continue;
}
if (!result.containsError(fieldName) && validator.required()) {
validRequired(fieldName, fieldValue, fieldCnName, result);
}
if (!result.containsError(fieldName) && validator.onlyAllowed() != null && validator.onlyAllowed().length > 0) {
validOnlyAllowed(fieldName, fieldValue, fieldCnName, Arrays.asList(validator.onlyAllowed()), result);
}
if (!result.containsError(fieldName) && validator.onlyAllowedEnumName() != null && validator.onlyAllowedEnumName().length > 0) {
Set enumNameSet = new HashSet<>();
for (Class extends Enum>> aClass : validator.onlyAllowedEnumName()) {
enumNameSet.addAll(getEnumNames(aClass));
}
validOnlyAllowed(fieldName, fieldValue, fieldCnName, enumNameSet, result);
}
if (!result.containsError(fieldName) && UtilString.isNotBlank(validator.onlyAllowedByKey())) {
ValidatorInterface validatorInterface = null;
try {
validatorInterface = SpringBeanUtil.getBean(ValidatorInterface.class);
} catch (Exception e) {
}
if (validatorInterface == null) {
logger.warn("ValidatorInterface 获取失败,onlyAllowedByKey 配置无效");
} else {
Collection allows = validatorInterface.onlyAllowedByKey(validator.onlyAllowedByKey());
validOnlyAllowed(fieldName, fieldValue, fieldCnName, allows, result);
}
}
if (!result.containsError(fieldName) && UtilString.isNotBlank(validator.minValue())) {
validMinValue(fieldName, fieldValue, fieldCnName, validator.minValue(), result);
}
if (!result.containsError(fieldName) && UtilString.isNotBlank(validator.maxValue())) {
validMaxValue(fieldName, fieldValue, fieldCnName, validator.maxValue(), result);
}
if (!result.containsError(fieldName) && validator.minLength() > 0) {
validMinLength(fieldName, fieldValue, fieldCnName, validator.minLength(), result);
}
if (!result.containsError(fieldName) && validator.maxLength() < Integer.MAX_VALUE) {
validMaxLength(fieldName, fieldValue, fieldCnName, validator.maxLength(), result);
}
if (!result.containsError(fieldName) && UtilString.isNotBlank(validator.strFormat())) {
validStrFormat(fieldName, fieldValue, fieldCnName, validator.strFormat(), result);
}
}
}
}
private boolean needValid(String[] tags) {
if (includeAllField) {
return true;
}
if (tags == null || tags.length == 0) {
return includeEmptyTagField;
}
for (String tag : tags) {
if (includeTagsField.contains(tag)) {
return true;
}
}
return false;
}
private Set getEnumNames(Class extends Enum>> enumObject) {
Set result = new HashSet<>();
for (Enum> anEnum : enumObject.getEnumConstants()) {
result.add(anEnum.name());
}
return result;
}
private String getFieldShowName(Field field, String validatorCnName) {
if (UtilString.isNotBlank(validatorCnName)) {
return validatorCnName;
}
if (field == null) {
return "";
}
String cnName = UtilClass.getAnnotationValue(field, CN_NAME_ANNOTATION_CLASS, "value", String.class);
if (UtilString.isNotBlank(cnName)) {
return cnName;
}
String apiModelValue = UtilClass.getAnnotationValue(field, API_MODEL_PROPERTY, "value", String.class);
if (UtilString.isNotBlank(apiModelValue)) {
return apiModelValue;
}
return field.getName();
}
private void validRequired(final String fieldName, Object fieldValue, final String fieldCnName, ValidatorResult result) {
boolean isnull;
if (fieldValue instanceof String) {
isnull = UtilString.isBlank((String) fieldValue);
} else {
isnull = (fieldValue == null);
}
if (isnull) {
result.setFails(true);
result.getFailsInfo().put(fieldName, "[" + fieldCnName + "]不能为空");
}
}
private void validMaxLength(final String fieldName, Object fieldValue, final String fieldCnName, int maxLength, ValidatorResult result) {
if (fieldValue == null) {
return;
}
boolean stringTooLength = ((fieldValue instanceof String) && ((String) fieldValue).length() > maxLength);
boolean sizeTooMax = (fieldValue instanceof Map && ((Map) fieldValue).size() > maxLength)
|| (fieldValue instanceof Collection && ((Collection) fieldValue).size() > maxLength);
if (stringTooLength || sizeTooMax) {
result.setFails(true);
String unit = stringTooLength ? "长度" : "数量";
result.getFailsInfo().put(fieldName, "[" + fieldCnName + "]的" + unit + "不能大于[" + maxLength + "]");
}
}
private void validMinLength(final String fieldName, Object fieldValue, final String fieldCnName, int minLength, ValidatorResult result) {
if (fieldValue == null) {
return;
}
boolean stringTooLength = ((fieldValue instanceof String) && ((String) fieldValue).length() < minLength);
boolean sizeTooMin = (fieldValue instanceof Map && ((Map) fieldValue).size() < minLength)
|| (fieldValue instanceof Collection && ((Collection) fieldValue).size() < minLength);
if (stringTooLength || sizeTooMin) {
result.setFails(true);
String unit = stringTooLength ? "长度" : "数量";
result.getFailsInfo().put(fieldName, "[" + fieldCnName + "]的" + unit + "不能小于[" + minLength + "]");
}
}
private void validMaxValue(final String fieldName, Object fieldValue, final String fieldCnName, String maxValue, ValidatorResult result) {
boolean pass = true;
if (fieldValue == null) {
pass = true;
} else if (fieldValue instanceof Date) {
Date maxValueObj = this.formatDate(maxValue);
if (maxValueObj == null) {
logger.warn("验证[{}]属性时出错:maxValue 设置的值[{}]无法转换成 Date 格式(已跳过验证)", fieldName, maxValue);
pass = true;
} else {
pass = maxValueObj.compareTo((Date) fieldValue) >= 0;
}
} else if (fieldValue instanceof BigDecimal) {
if (!UtilString.isBigDecimal(maxValue)) {
logger.warn("验证[{}]属性时出错:maxValue 设置的值无法转换成 BigDecimal 格式(已跳过验证)", fieldName);
pass = true;
} else {
BigDecimal maxValueObj = new BigDecimal(maxValue.replaceAll(",", ""));
pass = maxValueObj.compareTo((BigDecimal) fieldValue) >= 0;
}
} else if (fieldValue instanceof Double || fieldValue instanceof Float || fieldValue instanceof Integer || fieldValue instanceof Long) {
if (!maxValue.matches(UtilRegex.REGEX_NUMERIC)) {
logger.warn("验证[{}]属性时出错:maxValue 设置的值无法转换成数值格式(已跳过验证)", fieldName);
pass = true;
} else {
Double fieldValueObj = Double.valueOf(String.valueOf(fieldValue));
Double maxValueObj = Double.valueOf(maxValue);
pass = maxValueObj.compareTo(fieldValueObj) >= 0;
}
}
if (!pass) {
result.setFails(true);
result.getFailsInfo().put(fieldName, "[" + fieldCnName + "]的值不能大于[" + showValue(maxValue) + "]");
}
}
private void validMinValue(final String fieldName, Object fieldValue, final String fieldCnName, String minValue, ValidatorResult result) {
boolean pass = true;
if (fieldValue == null) {
pass = true;
} else if (fieldValue instanceof Date) {
Date minValueObj = this.formatDate(minValue);
if (minValueObj == null) {
logger.warn("验证[{}]属性时出错:minValue 设置的值[{}]无法转换成 Date 格式(已跳过验证)", fieldName, minValue);
pass = true;
} else {
pass = minValueObj.compareTo((Date) fieldValue) <= 0;
}
} else if (fieldValue instanceof BigDecimal) {
if (!UtilString.isBigDecimal(minValue)) {
logger.warn("验证[{}]属性时出错:minValue 设置的值无法转换成 BigDecimal 格式(已跳过验证)", fieldName);
pass = true;
} else {
BigDecimal minValueObj = new BigDecimal(minValue.replaceAll(",", ""));
pass = minValueObj.compareTo((BigDecimal) fieldValue) <= 0;
}
} else if (fieldValue instanceof Double || fieldValue instanceof Float || fieldValue instanceof Integer || fieldValue instanceof Long) {
if (!minValue.matches(UtilRegex.REGEX_NUMERIC)) {
logger.warn("验证[{}]属性时出错:minValue 设置的值无法转换成数值格式(已跳过验证)", fieldName);
pass = true;
} else {
Double fieldValueObj = Double.valueOf(String.valueOf(fieldValue));
Double minValueObj = Double.valueOf(minValue);
pass = minValueObj.compareTo(fieldValueObj) <= 0;
}
}
if (!pass) {
result.setFails(true);
result.getFailsInfo().put(fieldName, "[" + fieldCnName + "]的值不能小于[" + showValue(minValue) + "]");
}
}
// 注解中配置的值 => 错误时提示的值
// 例:now-7 => 7天前
private String showValue(String configString) {
if (UtilString.isBlank(configString)) {
return configString;
}
if ("now".equals(configString)) {
return "当前时间";
}
if (configString.startsWith("now+")) {
String addDay = configString.substring(4);
if (addDay.matches(UtilRegex.REGEX_NUMBER)) {
return Integer.valueOf(addDay) + "天后";
}
}
if (configString.startsWith("now-")) {
String addDay = configString.substring(4);
if (addDay.matches(UtilRegex.REGEX_NUMBER)) {
return Integer.valueOf(addDay) + "天前";
}
}
return configString;
}
// 格式化 Date 类型的校验值,支持:now、now-5、now+7 等字符串
private Date formatDate(String dateString) {
if ("now".equals(dateString)) {
return new Date();
}
if (dateString.startsWith("now+")) {
String addDay = dateString.substring(4);
if (addDay.matches(UtilRegex.REGEX_NUMBER)) {
return UtilDate.getLaterDay(new Date(), Integer.valueOf(addDay));
}
}
if (dateString.startsWith("now-")) {
String addDay = dateString.substring(4);
if (addDay.matches(UtilRegex.REGEX_NUMBER)) {
return UtilDate.getLaterDay(new Date(), Integer.valueOf(addDay) * (-1));
}
}
return UtilDate.format(dateString);
}
private void validOnlyAllowed(final String fieldName, Object fieldValue, final String fieldCnName, Collection allowedValues, ValidatorResult result) {
if (fieldValue == null) {
return;
}
String fieldStrValue = String.valueOf(fieldValue);
if ("".equals(fieldStrValue)) {
return;
}
if (allowedValues == null || allowedValues.size() == 0) {
result.setFails(true);
result.getFailsInfo().put(fieldName, "[" + fieldCnName + "]无有效取值");
return;
}
boolean pass = allowedValues.contains(fieldStrValue);
if (!pass) {
result.setFails(true);
result.getFailsInfo().put(fieldName, "[" + fieldCnName + "]只能取值" + allowedValues);
}
}
private void validStrFormat(final String fieldName, Object fieldValue, final String fieldCnName, String strFormat, ValidatorResult result) {
boolean pass = true;
String unPassReason = "";
if (fieldValue != null && (fieldValue instanceof String)) {
String fieldValueStr = (String) fieldValue;
if (UtilString.isNotBlank(fieldValueStr)) {
if (StrFormat.DATE_STR.equals(strFormat)) {
if (UtilDate.format(fieldValueStr) == null) {
pass = false;
unPassReason = "[" + fieldCnName + "]的值格式错误,只能是日期格式";
}
} else if (StrFormat.BIG_DECIMAL_STR.equals(strFormat)) {
if (!UtilString.isBigDecimal(fieldValueStr)) {
pass = false;
unPassReason = "[" + fieldCnName + "]的值格式错误,只能是数值格式";
}
} else {
logger.warn("验证[{}]属性时出错:strFormat 设置的值[{}]不支持(已跳过验证)", fieldName, strFormat);
}
}
}
if (!pass) {
result.setFails(true);
result.getFailsInfo().put(fieldName, unPassReason);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy