All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.diboot.core.util.V Maven / Gradle / Ivy

There is a newer version: 3.5.0
Show newest version
/*
 * 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 org.hibernate.validator.HibernateValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; 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; /** * 对象是否为空 */ 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; } 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(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; } 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(double[] array) { return array != null && array.length != 0; } public static boolean notEmpty(float[] 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(short[] array) { return array != null && array.length != 0; } public static boolean notEmpty(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; } /** * 全都不为空则返回true * * @param objs objs * @return true/false */ public static boolean isNoneEmpty(Object... objs) { return !isAnyEmpty(objs); } /** * 全为空则返回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 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; } 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(); } /** * 对象不为空且不为0 */ public static boolean notEmptyOrZero(Long longObj) { return longObj != null && longObj != 0; } /** * 对象不为空且不为0 */ public static boolean notEmptyOrZero(Integer intObj) { return intObj != null && intObj != 0; } /** * 集合中是否包含指定元素 * * @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, "非法的参数: " + 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, "非法的参数: " + 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, "非法的参数值: {}", 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 helper = new CardinalityHelper<>(sourceList, targetList); // 如果 两个Collection的统计结果 不一致 if (helper.cardinalityA.size() != helper.cardinalityB.size()) { return false; } // 遍历统计结果 for (final Object obj : helper.cardinalityA.keySet()) { // 相同元素 在两个Collection中的数量却不等 if (helper.freqA(obj) != helper.freqB(obj)) { return false; } } return true; } else if (source instanceof Map) { Map sourceMap = (Map) source, targetMap = (Map) target; if (sourceMap.size() != targetMap.size()) { return false; } else if (sourceMap.isEmpty()) { return true; } for (Map.Entry entry : sourceMap.entrySet()) { if (!equals(entry.getValue(), targetMap.get(entry.getKey()))) { return false; } } return true; } else { log.warn("暂未实现类型 " + source.getClass().getName() + "-" + target.getClass().getName() + " 的比对!"); return false; } } /** * 列表others中是否包含source * * @param source 查询对象 * @param others 可能值列表 * @param 类型 * @return others列表为空或者不包含source,则返回false */ @SafeVarargs public static boolean anyEquals(T source, T... others) { if (isEmpty(others)) { return false; } for (T other : others) { if (equals(source, other)) { return true; } } return false; } /** * 模糊对比是否相等(类型不同的转成String对比) */ public static boolean fuzzyEqual(Object source, Object target) { if (equals(source, target)) { return true; } // Boolean-String类型 if (source instanceof Boolean && target instanceof String) { return (boolean) source == V.isTrue((String) target); } if (target instanceof Boolean && source instanceof String) { return (boolean) target == V.isTrue((String) source); } // Date-String类型 else if (source instanceof Date && target instanceof String) { return D.getDateTime((Date) source).equals(target) || D.getDate((Date) source).equals(target); } else if (target instanceof Date && source instanceof String) { return D.getDateTime((Date) target).equals(source) || D.getDate((Date) target).equals(source); } else { return S.valueOf(source).equals(S.valueOf(target)); } } /** * 解析所有的验证错误信息,转换为JSON */ public static String getBindingError(BindingResult result) { if (result == null || !result.hasErrors()) { return null; } List errors = result.getAllErrors(); List allErrors = new ArrayList<>(errors.size()); String defaultMessage; for (ObjectError error : errors) { if (notEmpty(defaultMessage = error.getDefaultMessage())) { allErrors.add(defaultMessage.replaceAll("\"", "'")); } } return S.join(allErrors); } /** * 基于Bean中的validator注解校验 * * @return 违法约束的集合 */ public static Set> validateBean(T obj, Class... groups) { if (VALIDATOR == null) { VALIDATOR = Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator(); } return VALIDATOR.validate(obj, groups); } /** * 基于Bean中的validator注解校验 * * @return 违法约束的消息内容 */ public static String validateBeanErrMsg(T obj, Class... groups) { Set> errors = validateBean(obj, groups); if (isEmpty(errors)) { return null; } List allErrors = new ArrayList<>(errors.size()); for (ConstraintViolation err : errors) { allErrors.add(err.getMessage()); } return S.join(allErrors); } /** * Helper class to easily access cardinality properties of two collections. * * @param the element type */ private static class CardinalityHelper { /** * Contains the cardinality for each object in collection A. */ final Map cardinalityA; /** * Contains the cardinality for each object in collection B. */ final Map cardinalityB; /** * Create a new CardinalityHelper for two collections. * * @param a the first collection * @param b the second collection */ CardinalityHelper(final Iterable a, final Iterable b) { cardinalityA = getCardinalityMap(a); cardinalityB = getCardinalityMap(b); } /** * Returns a {@link Map} mapping each unique element in the given * {@link Collection} to an {@link Integer} representing the number * of occurrences of that element in the {@link Collection}. *

* Only those elements present in the collection will appear as * keys in the map. *

* * @param the type of object in the returned {@link Map}. This is a super type of <I>. * @param coll the collection to get the cardinality map for, must not be null * @return the populated cardinality map * @throws NullPointerException if coll is null */ public static Map getCardinalityMap(final Iterable coll) { Objects.requireNonNull(coll, "coll"); final Map count = new HashMap<>(); for (final O obj : coll) { count.merge(obj, 1, Integer::sum); } return count; } /** * Returns the maximum frequency of an object. * * @param obj the object * @return the maximum frequency of the object */ public final int max(final Object obj) { return Math.max(freqA(obj), freqB(obj)); } /** * Returns the minimum frequency of an object. * * @param obj the object * @return the minimum frequency of the object */ public final int min(final Object obj) { return Math.min(freqA(obj), freqB(obj)); } /** * Returns the frequency of this object in collection A. * * @param obj the object * @return the frequency of the object in collection A */ public int freqA(final Object obj) { return getFreq(obj, cardinalityA); } /** * Returns the frequency of this object in collection B. * * @param obj the object * @return the frequency of the object in collection B */ public int freqB(final Object obj) { return getFreq(obj, cardinalityB); } private int getFreq(final Object obj, final Map freqMap) { final Integer count = freqMap.get(obj); if (count != null) { return count; } return 0; } } }