com.diboot.core.util.V Maven / Gradle / Ivy
Show all versions of diboot-core Show documentation
/*
* Copyright (c) 2015-2020, www.dibo.ltd ([email protected]).
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.diboot.core.util;
import com.diboot.core.data.query.CriteriaItem;
import com.diboot.core.data.query.QueryCondition;
import com.diboot.core.exception.BusinessException;
import com.diboot.core.vo.Status;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import org.hibernate.validator.HibernateValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import java.lang.reflect.Array;
import java.util.*;
import java.util.regex.Pattern;
/**
* Validator校验类
*
* @author [email protected]
* @version v2.0
* @date 2019/01/01
*/
@SuppressWarnings("unused")
public class V {
private static final Logger log = LoggerFactory.getLogger(V.class);
/**
* hibernate注解验证
*/
private static Validator VALIDATOR = null;
// region 判空方法
/* ================================================== 判空方法 =================================================== */
/**
* 对象是否为空
*/
public static boolean isEmpty(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof CharSequence) {
return isEmpty((CharSequence) obj);
} else if (obj instanceof Collection) {
return isEmpty((Collection>) obj);
} else if (obj instanceof Map) {
return isEmpty((Map, ?>) obj);
} else if (obj.getClass().isArray()) {
return Array.getLength(obj) == 0;
} else if (obj instanceof Iterator) {
return isEmpty((Iterator>) obj);
} else if (obj instanceof Iterable) {
return isEmpty((Iterable>) obj);
} else if (obj instanceof Enumeration) {
return isEmpty((Enumeration>) obj);
}
return false;
}
/**
* 字符串是否为空
*/
public static boolean isEmpty(CharSequence value) {
return S.isBlank(value);
}
/**
* 字符串是否为空
*/
public static boolean isEmpty(String value) {
return S.isBlank(value);
}
/**
* 集合为空
*/
public static boolean isEmpty(Collection list) {
return list == null || list.isEmpty();
}
/**
* 字符串数组是否不为空
*/
public static boolean isEmpty(String[] values) {
return values == null || values.length == 0;
}
/**
* Map为空
*/
public static boolean isEmpty(Map obj) {
return obj == null || obj.isEmpty();
}
public static boolean isEmpty(Iterator iterator) {
return iterator == null || !iterator.hasNext();
}
public static boolean isEmpty(Iterable iterable) {
return iterable == null || isEmpty(iterable.iterator());
}
public static boolean isEmpty(Enumeration enumeration) {
return enumeration == null || !enumeration.hasMoreElements();
}
public static boolean isEmpty(boolean[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(byte[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(char[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(double[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(float[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(int[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(long[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(short[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(Object[] array) {
return array == null || array.length == 0;
}
/**
* 任意元素为空则返回true
*
* @param objs objs
* @return true/false
*/
public static boolean isAnyEmpty(Object... objs) {
if (isEmpty(objs)) {
return true;
}
for (Object obj : objs) {
if (isEmpty(obj)) {
return true;
}
}
return false;
}
public static boolean isAnyEmpty(Collection collection) {
if (isEmpty(collection)) {
return true;
}
for (T obj : collection) {
if (isEmpty(obj)) {
return true;
}
}
return false;
}
/**
* 全为空则返回true
*
* @param objs objs
* @return true/false
*/
public static boolean isAllEmpty(Object... objs) {
if (isEmpty(objs)) {
return true;
}
for (Object obj : objs) {
if (notEmpty(obj)) {
return false;
}
}
return true;
}
public static boolean isAllEmpty(Collection collection) {
if (isEmpty(collection)) {
return true;
}
for (T obj : collection) {
if (notEmpty(obj)) {
return false;
}
}
return true;
}
/* ================================================== end ======================================================= */
// endregion
// region 非空判断方法
/* ================================================== 非空判断方法 ================================================ */
/**
* 对象是否为空
*/
public static boolean notEmpty(Object obj) {
if (obj == null) {
return false;
} else if (obj instanceof CharSequence) {
return notEmpty((CharSequence) obj);
} else if (obj instanceof Collection) {
return notEmpty((Collection>) obj);
} else if (obj instanceof Map) {
return notEmpty((Map, ?>) obj);
} else if (obj.getClass().isArray()) {
return Array.getLength(obj) != 0;
} else if (obj instanceof Iterator) {
return notEmpty((Iterator>) obj);
} else if (obj instanceof Iterable) {
return notEmpty((Iterable>) obj);
} else if (obj instanceof Enumeration) {
return notEmpty((Enumeration>) obj);
}
return true;
}
/**
* 字符串不为空,或者不是所有字符都为whitespace字符
*/
public static boolean notEmpty(CharSequence value) {
return S.isNotBlank(value);
}
/**
* 字符串不为空,或者不是所有字符都为whitespace字符
*/
public static boolean notEmpty(String value) {
return S.isNotBlank(value);
}
/**
* 字符串数组是否不为空
*/
public static boolean notEmpty(String[] values) {
return values != null && values.length > 0;
}
/**
* 集合不为空
*/
public static boolean notEmpty(Collection list) {
return list != null && !list.isEmpty();
}
/**
* Map不为空
*/
public static boolean notEmpty(Map obj) {
return obj != null && !obj.isEmpty();
}
public static boolean notEmpty(Iterator iterator) {
return iterator != null && iterator.hasNext();
}
public static boolean notEmpty(Iterable iterable) {
return iterable != null && notEmpty(iterable.iterator());
}
public static boolean notEmpty(Enumeration enumeration) {
return enumeration != null && enumeration.hasMoreElements();
}
public static boolean notEmpty(boolean[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(byte[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(char[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(short[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(int[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(long[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(double[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(float[] array) {
return array != null && array.length != 0;
}
public static boolean notEmpty(Object[] array) {
return array != null && array.length != 0;
}
/**
* 对象不为空且不为0
*/
public static boolean notEmptyOrZero(Long longObj) {
return longObj != null && longObj != 0;
}
/**
* 对象不为空且不为0
*/
public static boolean notEmptyOrZero(Integer intObj) {
return intObj != null && intObj != 0;
}
/**
* 全都不为空则返回true
*
* @param objs objs
* @return true/false
*/
public static boolean isNoneEmpty(Object... objs) {
return !isAnyEmpty(objs);
}
public static boolean isNoneEmpty(Collection collection) {
return !isAnyEmpty(collection);
}
/* ================================================== end ======================================================= */
// endregion
/**
* 集合中是否包含指定元素
*
* @param collection 集合
* @param target 查找元素
* @return 集合为空或者不包含元素,则返回false
*/
public static boolean contains(Collection collection, T target) {
return collection != null && collection.contains(target);
}
/**
* 集合中是否包含指定字符串或其大写字符串
*
* @param collection 集合
* @param target 查找字符串
* @return 集合为空或者不包含元素,则返回false
*/
public static boolean containsIgnoreCase(Collection collection, String target) {
return collection != null && (collection.contains(target) || collection.contains(target.toLowerCase()) || collection.contains(target.toUpperCase()));
}
/**
* 集合中是否不包含指定元素
*
* @param collection 集合
* @param target 查找元素
* @return 集合为空或者包含元素,则返回false
*/
public static boolean notContains(Collection collection, T target) {
return collection != null && !collection.contains(target);
}
/**
* 集合中是否不包含指定字符串或其大写字符串
*
* @param collection 集合
* @param target 查找字符串
* @return 集合为空或者不包含元素,则返回false
*/
public static boolean notContainsIgnoreCase(Collection collection, String target) {
return !(containsIgnoreCase(collection, target));
}
/**
* 判断是否为数字(允许小数点)
*
* @return true Or false
*/
public static boolean isNumber(String str) {
String regex = "^(-?[1-9]\\d*\\.?\\d*)|(-?0\\.\\d*[1-9])|(-?[0])|(-?[0]\\.\\d*)$";
return str.matches(regex);
}
/**
* 判断是否为正确的邮件格式
*
* @return boolean
*/
public static boolean isEmail(String str) {
if (isEmpty(str)) {
return false;
}
return str.matches("^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$");
}
/**
* 判断字符串是否为电话号码
*
* @return boolean
*/
public static boolean isPhone(String str) {
if (isEmpty(str)) {
return false;
}
boolean valid = str.matches("^1\\d{10}$");
if (!valid) {
valid = str.matches("^[0|4]\\d{2,3}-?\\d{7,8}$");
}
return valid;
}
/**
* 对参数值做安全检查
*/
public static void securityCheck(String... paramValues) {
if (isEmpty(paramValues)) {
return;
}
for (String param : paramValues) {
if (!V.isValidSqlParam(param)) {
throw new BusinessException(Status.FAIL_VALIDATION, "exception.business.v.securityCheck.param", param);
}
}
}
/**
* 对参数值做安全检查
*/
public static void securityCheck(Object... paramValues) {
if (isEmpty(paramValues)) {
return;
}
for (Object param : paramValues) {
if (!V.isValidSqlParam(param)) {
throw new BusinessException(Status.FAIL_VALIDATION, "exception.business.v.securityCheck.param", param);
}
}
}
/**
* SQL注入关键字过滤
*/
private static final Pattern SQL_INJECT_PATTERN = Pattern.compile("(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)", Pattern.CASE_INSENSITIVE);
/**
* SQL查询条件安全检查
* @param queryCondition
* @throws BusinessException
*/
public static void securityCheck(QueryCondition queryCondition) throws BusinessException {
if(V.isEmpty(queryCondition.getCriteriaList())){
return;
}
for (CriteriaItem entry: queryCondition.getCriteriaList()) {
securityCheck(entry.getField());
if(entry.getValue() != null && entry.getValue() instanceof String){
String value = (String)entry.getValue();
if(SQL_INJECT_PATTERN.matcher(value.toLowerCase()).find()){
log.warn("非法的参数值: {}", entry.getValue());
throw new BusinessException(Status.FAIL_VALIDATION, "exception.business.v.securityCheck.paramValue", entry.getValue());
}
}
}
}
/**
* 是否为合法的数据库列参数(orderBy等参数安全检查)
*/
private static final Pattern PATTERN = Pattern.compile("^[0-9A-Za-z_][\\w.:]*$");
public static boolean isValidSqlParam(Object sqlParam) {
if (isEmpty(sqlParam)) {
return true;
}
if (sqlParam instanceof Collection) {
Collection collection = (Collection) sqlParam;
for (Iterator iter = collection.iterator(); iter.hasNext();) {
Object param = iter.next();
boolean valid = isValidSqlParam(param);
if(!valid) {
log.debug("不符合安全规范的参数: {}", S.valueOf(param));
return false;
}
}
return true;
}
else if (sqlParam.getClass().isArray()) {
Object[] paramArray = (Object[]) sqlParam;
for(Object param : paramArray){
boolean valid = isValidSqlParam(param);
if(!valid) {
log.debug("不符合安全规范的参数: {}", S.valueOf(param));
return false;
}
}
return true;
}
else if(sqlParam instanceof Map) {
Map map = (Map) sqlParam;
for(Object key : map.keySet()){
boolean valid = isValidSqlParam(key);
if(!valid) {
log.debug("不符合安全规范的参数: {}", S.valueOf(key));
return false;
}
}
for(Object val : map.values()){
boolean valid = isValidSqlParam(val);
if(!valid) {
log.debug("不符合安全规范的参数: {}", S.valueOf(val));
return false;
}
}
return true;
}
return PATTERN.matcher(S.valueOf(sqlParam)).matches();
}
/**
* 是否boolean值范围
*/
private static final Set TRUE_SET = new HashSet<>(Arrays.asList(
"true", "是", "y", "yes", "1"
));
private static final Set FALSE_SET = new HashSet<>(Arrays.asList(
"false", "否", "n", "no", "0"
));
/**
* 是否为boolean类型
*/
public static boolean isValidBoolean(String value) {
if (value == null) {
return false;
}
value = S.trim(value).toLowerCase();
return TRUE_SET.contains(value) || FALSE_SET.contains(value);
}
/**
* 转换为boolean类型, 并判定是否为true
*/
public static boolean isTrue(String value) {
if (value == null) {
return false;
}
value = S.trim(value).toLowerCase();
return TRUE_SET.contains(value);
}
/**
* 是否是false
* 不要再写"xxx == false"了
*
* @param expression bool表达式
* @return 入参为false时返回true
*/
public static boolean isFalse(boolean expression) {
return !expression;
}
/**
* 根据指定规则校验字符串的值是否合法
*/
@SuppressWarnings("StatementWithEmptyBody")
@Deprecated
public static String validate(String value, String validation) {
if (isEmpty(validation)) {
return null;
}
List errorMsgList = new ArrayList<>();
String[] rules = validation.split(",");
for (String rule : rules) {
if ("NotNull".equalsIgnoreCase(rule)) {
if (isEmpty(value)) {
errorMsgList.add("不能为空");
}
} else if ("Number".equalsIgnoreCase(rule)) {
if (!isNumber(value)) {
errorMsgList.add("非数字格式");
}
} else if ("Boolean".equalsIgnoreCase(rule)) {
if (!isValidBoolean(value)) {
errorMsgList.add("非Boolean格式");
}
} else if ("Date".equalsIgnoreCase(rule)) {
if (D.fuzzyConvert(value) == null) {
errorMsgList.add("非日期格式");
}
} else if (rule.toLowerCase().startsWith("length")) {
String range = rule.substring(rule.indexOf("(") + 1, rule.lastIndexOf(")"));
if (range.contains("-")) {
String[] arr = range.split("-");
if (notEmpty(arr[0])) {
if (V.isEmpty(value) || value.length() < Integer.parseInt(arr[0])) {
errorMsgList.add("长度少于最小限制数: " + arr[0]);
}
}
if (notEmpty(arr[1])) {
if (V.notEmpty(value)) {
if (value.length() > Integer.parseInt(arr[1])) {
errorMsgList.add("长度超出最大限制数: " + arr[1]);
}
}
}
} else {
if (V.isEmpty(value) || value.length() != Integer.parseInt(range)) {
errorMsgList.add("长度限制: " + range + "位");
}
}
} else if ("Email".equalsIgnoreCase(rule)) {
if (!isEmail(value)) {
errorMsgList.add("非Email格式");
}
} else if ("Phone".equalsIgnoreCase(rule)) {
if (!isPhone(value)) {
errorMsgList.add("非电话号码格式");
}
} else {
// 无法识别的格式
}
}
// 返回校验不通过的结果
if (errorMsgList.isEmpty()) {
return null;
} else {
return S.join(errorMsgList);
}
}
/**
* 判定两个对象是否不同类型或不同值
*/
public static boolean notEquals(Object source, Object target) {
return !equals(source, target);
}
/**
* 判定两个对象是否类型相同值相等
*/
public static boolean equals(T source, T target) {
if (source == target) {
return true;
} else if (source == null || target == null) {
return false;
}
else if (source.getClass() != target.getClass() && !(source instanceof Map && target instanceof Map)) {
// 根据equals设计原则,类型不一致,直接false(仅允许HashMap、LinkedHashMap的差异)
// 避免子类与父类、子类与子类比较时可能出现的问题
log.warn("source: {} 和 target: {} 类型不匹配", source.getClass(), target.getClass());
return false;
} else if (source instanceof Class) {
return ((Class>) source).getName().equals(((Class>) target).getName());
} else if (source instanceof Comparable) {
// 部分java早期类的equals和compareTo结果不一致,避免直接调用equals
//noinspection unchecked
return ((Comparable) source).compareTo(target) == 0;
} else if (source instanceof Collection) {
Collection> sourceList = (Collection>) source, targetList = (Collection>) target;
// size不等
if (sourceList.size() != targetList.size()) {
return false;
} else if (sourceList.isEmpty()) {
// size相等,且一个为空集合
return true;
}
if (source instanceof Set) {
//noinspection SuspiciousMethodCalls
return ((Set>) source).containsAll(targetList);
}
// copy from org.apache.commons.collections4.CollectionUtils.isEqualCollection()
// 分别统计 Collection中 元素对应的数量
CardinalityHelper