valueTypeRef) {
+ if (null == json || "".equals(json)) {
+ return null;
+ }
+ try {
+ return mapper.readValue(json, valueTypeRef);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
diff --git a/flyfish-common/src/main/java/com/flyfish/framework/utils/ReflectionUtils.java b/flyfish-common/src/main/java/com/flyfish/framework/utils/ReflectionUtils.java
new file mode 100644
index 0000000..b86c398
--- /dev/null
+++ b/flyfish-common/src/main/java/com/flyfish/framework/utils/ReflectionUtils.java
@@ -0,0 +1,338 @@
+package com.flyfish.framework.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.springframework.util.Assert;
+
+import java.lang.reflect.*;
+
+/**
+ * 反射工具类.
+ * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
+ *
+ * @author calvin
+ * @version 2013-01-15
+ */
+@SuppressWarnings("rawtypes")
+@Slf4j
+public class ReflectionUtils {
+
+ private static final String SETTER_PREFIX = "set";
+
+ private static final String GETTER_PREFIX = "get";
+
+ private static final String CGLIB_CLASS_SEPARATOR = "$$";
+
+ /**
+ * 调用Getter方法.
+ * 支持多级,如:对象名.对象名.方法
+ */
+ public static Object invokeGetter(Object obj, String propertyName) {
+ Object object = obj;
+ for (String name : StringUtils.split(propertyName, ".")) {
+ String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+ object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
+ }
+ return object;
+ }
+
+ /**
+ * 调用Setter方法, 仅匹配方法名。
+ * 支持多级,如:对象名.对象名.方法
+ */
+ public static void invokeSetter(Object obj, String propertyName, Object value) {
+ Object object = obj;
+ String[] names = StringUtils.split(propertyName, ".");
+ for (int i = 0; i < names.length; i++) {
+ if (i < names.length - 1) {
+ String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+ object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
+ } else {
+ String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+ invokeMethodByName(object, setterMethodName, new Object[]{value});
+ }
+ }
+ }
+
+ /**
+ * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
+ */
+ public static Object getFieldValue(final Object obj, final String fieldName) {
+ Field field = getAccessibleField(obj, fieldName);
+
+ if (field == null) {
+ throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
+ }
+
+ Object result = null;
+ try {
+ result = field.get(obj);
+ } catch (IllegalAccessException e) {
+ log.error("不可能抛出的异常{}", e.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
+ */
+ public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
+ Field field = getAccessibleField(obj, fieldName);
+
+ if (field == null) {
+ log.error("Could not find field [" + fieldName + "] on target [" + obj + "]");
+ return;
+ //throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
+ }
+ try {
+ field.set(obj, convert(value, field.getType()));
+ } catch (IllegalAccessException e) {
+ log.error("不可能抛出的异常:{}", e.getMessage());
+ }
+ }
+
+ public static Object convert(Object object, Class> type) {
+ if (object instanceof Number) {
+ Number number = (Number) object;
+ if (type.equals(byte.class) || type.equals(Byte.class)) {
+ return number.byteValue();
+ }
+ if (type.equals(short.class) || type.equals(Short.class)) {
+ return number.shortValue();
+ }
+ if (type.equals(int.class) || type.equals(Integer.class)) {
+ return number.intValue();
+ }
+ if (type.equals(long.class) || type.equals(Long.class)) {
+ return number.longValue();
+ }
+ if (type.equals(float.class) || type.equals(Float.class)) {
+ return number.floatValue();
+ }
+ if (type.equals(double.class) || type.equals(Double.class)) {
+ return number.doubleValue();
+ }
+ }
+ if (type.equals(String.class)) {
+ return object == null ? "" : object.toString();
+ }
+ return object;
+ }
+
+ /**
+ * 直接调用对象方法, 无视private/protected修饰符.
+ * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
+ * 同时匹配方法名+参数类型,
+ */
+ public static Object invokeMethod(final Object obj, final String methodName, final Class>[] parameterTypes,
+ final Object[] args) {
+ Method method = getAccessibleMethod(obj, methodName, parameterTypes);
+ if (method == null) {
+ throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
+ }
+
+ try {
+ return method.invoke(obj, args);
+ } catch (Exception e) {
+ throw convertReflectionExceptionToUnchecked(e);
+ }
+ }
+
+ /**
+ * 直接调用对象方法, 无视private/protected修饰符,
+ * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
+ * 只匹配函数名,如果有多个同名函数调用第一个。
+ */
+ public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
+ Method method = getAccessibleMethodByName(obj, methodName);
+ if (method == null) {
+ throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
+ }
+
+ try {
+ return method.invoke(obj, args);
+ } catch (Exception e) {
+ throw convertReflectionExceptionToUnchecked(e);
+ }
+ }
+
+ /**
+ * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
+ *
+ * 如向上转型到Object仍无法找到, 返回null.
+ */
+ public static Field getAccessibleField(final Object obj, final String fieldName) {
+ Validate.notNull(obj, "object can't be null");
+ Validate.notBlank(fieldName, "fieldName can't be blank");
+ for (Class> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
+ try {
+ Field field = superClass.getDeclaredField(fieldName);
+ makeAccessible(field);
+ return field;
+ } catch (NoSuchFieldException e) {//NOSONAR
+ // Field不在当前类定义,继续向上转型
+ continue;// new add
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
+ * 如向上转型到Object仍无法找到, 返回null.
+ * 匹配函数名+参数类型。
+ *
+ * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
+ */
+ public static Method getAccessibleMethod(final Object obj, final String methodName,
+ final Class>... parameterTypes) {
+ Validate.notNull(obj, "object can't be null");
+ Validate.notBlank(methodName, "methodName can't be blank");
+
+ for (Class> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
+ try {
+ Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
+ makeAccessible(method);
+ return method;
+ } catch (NoSuchMethodException e) {
+ // Method不在当前类定义,继续向上转型
+ continue;// new add
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
+ * 如向上转型到Object仍无法找到, 返回null.
+ * 只匹配函数名。
+ *
+ * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
+ */
+ public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
+ Validate.notNull(obj, "object can't be null");
+ Validate.notBlank(methodName, "methodName can't be blank");
+
+ for (Class> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
+ Method[] methods = searchType.getDeclaredMethods();
+ for (Method method : methods) {
+ if (method.getName().equals(methodName)) {
+ makeAccessible(method);
+ return method;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
+ */
+ public static void makeAccessible(Method method) {
+ if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
+ && !method.isAccessible()) {
+ method.setAccessible(true);
+ }
+ }
+
+ /**
+ * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
+ */
+ public static void makeAccessible(Field field) {
+ if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
+ .isFinal(field.getModifiers())) && !field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ }
+
+ /**
+ * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
+ * 如无法找到, 返回Object.class.
+ * eg.
+ * public UserDao extends HibernateDao
+ *
+ * @param clazz The class to introspect
+ * @return the first generic declaration, or Object.class if cannot be determined
+ */
+ @SuppressWarnings("unchecked")
+ public static Class getClassGenricType(final Class clazz) {
+ return getClassGenricType(clazz, 0);
+ }
+
+ /**
+ * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
+ * 如无法找到, 返回Object.class.
+ *
+ * 如public UserDao extends HibernateDao
+ *
+ * @param clazz clazz The class to introspect
+ * @param index the Index of the generic ddeclaration,start from 0.
+ * @return the index generic declaration, or Object.class if cannot be determined
+ */
+ public static Class getClassGenricType(final Class clazz, final int index) {
+
+ Type genType = clazz.getGenericSuperclass();
+
+ if (!(genType instanceof ParameterizedType)) {
+ log.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
+ return Object.class;
+ }
+
+ Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
+
+ if (index >= params.length || index < 0) {
+ log.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ + params.length);
+ return Object.class;
+ }
+ if (!(params[index] instanceof Class)) {
+ log.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
+ return Object.class;
+ }
+
+ return (Class) params[index];
+ }
+
+ public static Class> getUserClass(Object instance) {
+ Assert.notNull(instance, "Instance must not be null");
+ Class clazz = instance.getClass();
+ if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
+ Class> superClass = clazz.getSuperclass();
+ if (superClass != null && !Object.class.equals(superClass)) {
+ return superClass;
+ }
+ }
+ return clazz;
+
+ }
+
+ /**
+ * 将反射时的checked exception转换为unchecked exception.
+ */
+ public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
+ if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
+ || e instanceof NoSuchMethodException) {
+ return new IllegalArgumentException(e);
+ } else if (e instanceof InvocationTargetException) {
+ return new RuntimeException(((InvocationTargetException) e).getTargetException());
+ } else if (e instanceof RuntimeException) {
+ return (RuntimeException) e;
+ }
+ return new RuntimeException("Unexpected Checked Exception.", e);
+ }
+
+ /**
+ * 判断某个对象是否拥有某个属性
+ *
+ * @param obj 对象
+ * @param fieldName 属性名
+ * @return 有属性返回true
+ * 无属性返回false
+ */
+ public static boolean hasField(final Object obj, final String fieldName) {
+ Field field = getAccessibleField(obj, fieldName);
+ return field != null;
+
+ }
+}
diff --git a/flyfish-common/src/main/java/com/flyfish/framework/utils/StringHelper.java b/flyfish-common/src/main/java/com/flyfish/framework/utils/StringHelper.java
new file mode 100644
index 0000000..59a58ab
--- /dev/null
+++ b/flyfish-common/src/main/java/com/flyfish/framework/utils/StringHelper.java
@@ -0,0 +1,10 @@
+package com.flyfish.framework.utils;
+
+/**
+ * Created by wangyu on 2017/9/10.
+ */
+public class StringHelper {
+ public static String getObjectValue(Object obj) {
+ return obj == null ? "" : obj.toString();
+ }
+}
diff --git a/flyfish-common/src/main/java/com/flyfish/framework/utils/TreeUtil.java b/flyfish-common/src/main/java/com/flyfish/framework/utils/TreeUtil.java
new file mode 100644
index 0000000..0241ede
--- /dev/null
+++ b/flyfish-common/src/main/java/com/flyfish/framework/utils/TreeUtil.java
@@ -0,0 +1,75 @@
+package com.flyfish.framework.utils;
+
+
+import com.flyfish.framework.bean.TreeNode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Wangyu on 2017/6/12.
+ */
+public class TreeUtil {
+ /**
+ * 两层循环实现建树
+ *
+ * @param treeNodes 传入的树节点列表
+ * @return
+ */
+ public static List bulid(List treeNodes, Object root) {
+
+ List trees = new ArrayList();
+
+ for (T treeNode : treeNodes) {
+
+ if (root.equals(treeNode.getParentId())) {
+ trees.add(treeNode);
+ }
+
+ for (T it : treeNodes) {
+ if (it.getParentId() == treeNode.getId()) {
+ if (treeNode.getChildren() == null) {
+ treeNode.setChildren(new ArrayList());
+ }
+ treeNode.add(it);
+ }
+ }
+ }
+ return trees;
+ }
+
+ /**
+ * 使用递归方法建树
+ *
+ * @param treeNodes
+ * @return
+ */
+ public static List buildByRecursive(List treeNodes, Object root) {
+ List trees = new ArrayList();
+ for (T treeNode : treeNodes) {
+ if (root.equals(treeNode.getParentId())) {
+ trees.add(findChildren(treeNode, treeNodes));
+ }
+ }
+ return trees;
+ }
+
+ /**
+ * 递归查找子节点
+ *
+ * @param treeNodes
+ * @return
+ */
+ public static T findChildren(T treeNode, List treeNodes) {
+ for (T it : treeNodes) {
+ if (treeNode.getId() == it.getParentId()) {
+ if (treeNode.getChildren() == null) {
+ treeNode.setChildren(new ArrayList());
+ }
+ treeNode.add(findChildren(it, treeNodes));
+ }
+ }
+ return treeNode;
+ }
+
+}
diff --git a/flyfish-common/src/main/java/com/flyfish/framework/utils/UUIDUtils.java b/flyfish-common/src/main/java/com/flyfish/framework/utils/UUIDUtils.java
new file mode 100644
index 0000000..de6f803
--- /dev/null
+++ b/flyfish-common/src/main/java/com/flyfish/framework/utils/UUIDUtils.java
@@ -0,0 +1,28 @@
+package com.flyfish.framework.utils;
+
+import java.util.UUID;
+
+/**
+ * Created by wangyu on 2017/9/27.
+ */
+public class UUIDUtils {
+ public static String[] chars = new String[]{"a", "b", "c", "d", "e", "f",
+ "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
+ "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
+ "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
+ "W", "X", "Y", "Z"};
+
+
+ public static String generateShortUuid() {
+ StringBuffer shortBuffer = new StringBuffer();
+ String uuid = UUID.randomUUID().toString().replace("-", "");
+ for (int i = 0; i < 8; i++) {
+ String str = uuid.substring(i * 4, i * 4 + 4);
+ int x = Integer.parseInt(str, 16);
+ shortBuffer.append(chars[x % 0x3E]);
+ }
+ return shortBuffer.toString();
+
+ }
+}
diff --git a/flyfish-data/pom.xml b/flyfish-data/pom.xml
new file mode 100644
index 0000000..cde41ee
--- /dev/null
+++ b/flyfish-data/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+ flyfish-framework
+ com.flyfish.framework
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ flyfish-data
+
+
+
+ com.flyfish.framework
+ flyfish-common
+ ${project.version}
+
+
+
+ org.springframework.data
+ spring-data-mongodb
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb-reactive
+
+
+
+
\ No newline at end of file
diff --git a/flyfish-data/src/main/java/com/flyfish/framework/auditor/BeanAuditor.java b/flyfish-data/src/main/java/com/flyfish/framework/auditor/BeanAuditor.java
new file mode 100644
index 0000000..b381493
--- /dev/null
+++ b/flyfish-data/src/main/java/com/flyfish/framework/auditor/BeanAuditor.java
@@ -0,0 +1,20 @@
+package com.flyfish.framework.auditor;
+
+import com.flyfish.framework.domain.base.Domain;
+
+/**
+ * 负责补全或者生成默认值(仅针对新建)
+ *
+ * @author wybab
+ */
+public interface BeanAuditor {
+
+ /**
+ * 对实体进行审查,并补全相关字段
+ *
+ * @param data 原数据
+ * @return 结果
+ */
+ void audit(T data);
+
+}
diff --git a/flyfish-data/src/main/java/com/flyfish/framework/auditor/OperationAuditor.java b/flyfish-data/src/main/java/com/flyfish/framework/auditor/OperationAuditor.java
new file mode 100644
index 0000000..3912c35
--- /dev/null
+++ b/flyfish-data/src/main/java/com/flyfish/framework/auditor/OperationAuditor.java
@@ -0,0 +1,36 @@
+package com.flyfish.framework.auditor;
+
+import com.flyfish.framework.context.UserContext;
+import com.flyfish.framework.domain.base.AuditDomain;
+import com.flyfish.framework.domain.po.User;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class OperationAuditor implements BeanAuditor {
+
+ private final UserContext userContext;
+
+ /**
+ * 对实体进行审查,并补全相关字段
+ *
+ * @param data 原数据
+ * @return 结果
+ */
+ @Override
+ public void audit(AuditDomain data) {
+ User currentUser = userContext.currentUser();
+ if (null != currentUser) {
+ if (StringUtils.isNotBlank(data.getId())) {
+ data.setModifierId(currentUser.getId());
+ data.setModifier(currentUser.getModifier());
+ } else {
+ data.setCreatorId(currentUser.getId());
+ data.setCreator(currentUser.getName());
+ data.setModifierId(currentUser.getModifierId());
+ }
+ }
+ }
+}
diff --git a/flyfish-data/src/main/java/com/flyfish/framework/auditor/UserAuditor.java b/flyfish-data/src/main/java/com/flyfish/framework/auditor/UserAuditor.java
new file mode 100644
index 0000000..44db7d3
--- /dev/null
+++ b/flyfish-data/src/main/java/com/flyfish/framework/auditor/UserAuditor.java
@@ -0,0 +1,33 @@
+package com.flyfish.framework.auditor;
+
+import com.flyfish.framework.context.UserContext;
+import com.flyfish.framework.domain.base.Domain;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+
+/**
+ * 用户上下文审查工具
+ *
+ * @author wangyu
+ */
+@Component
+@RequiredArgsConstructor
+public class UserAuditor implements AuditorAware {
+
+ private final UserContext userContext;
+
+ /**
+ * 在异步上下文中获取结果
+ *
+ * @return 结果
+ */
+ @Override
+ public Optional getCurrentAuditor() {
+ return Optional.ofNullable(userContext.currentUser())
+ .map(Domain::getName);
+ }
+
+}
diff --git a/flyfish-data/src/main/java/com/flyfish/framework/builder/CriteriaBuilder.java b/flyfish-data/src/main/java/com/flyfish/framework/builder/CriteriaBuilder.java
new file mode 100644
index 0000000..706d296
--- /dev/null
+++ b/flyfish-data/src/main/java/com/flyfish/framework/builder/CriteriaBuilder.java
@@ -0,0 +1,237 @@
+package com.flyfish.framework.builder;
+
+import com.flyfish.framework.context.DateContext;
+import com.flyfish.framework.domain.base.Domain;
+import com.flyfish.framework.domain.base.Qo;
+import lombok.Getter;
+import lombok.Setter;
+import org.bson.types.ObjectId;
+import org.springframework.beans.BeanUtils;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+
+/**
+ * 查询构建器
+ *
+ * @author wybab
+ */
+public final class CriteriaBuilder {
+
+ private Qo qo;
+
+ private Map> functionMap = new HashMap<>();
+
+ private Map keyMapper = new HashMap<>();
+
+ /**
+ * 构造器,接受一个qo
+ *
+ * @param qo 查询实体
+ * @param 泛型,实体
+ * @return 结果
+ */
+ public static CriteriaBuilder accept(Qo qo) {
+ CriteriaBuilder builder = new CriteriaBuilder<>();
+ builder.qo = qo;
+ return builder;
+ }
+
+ /**
+ * 添加策略
+ *
+ * @param key 键
+ * @param function 方法
+ * @param field 域的键值
+ * @return 结果
+ */
+ public CriteriaBuilder with(String key, String field, BiFunction function) {
+ this.functionMap.putIfAbsent(key, function);
+ keyMapper.putIfAbsent(key, field);
+ return this;
+ }
+
+ /**
+ * 添加策略
+ *
+ * @param key 键
+ * @param function 方法
+ * @return 结果
+ */
+ public CriteriaBuilder with(String key, BiFunction function) {
+ this.functionMap.putIfAbsent(key, function);
+ return this;
+ }
+
+ /**
+ * 添加策略
+ *
+ * @param key 键
+ * @return 结果
+ */
+ public CriteriaBuilder with(String... key) {
+ Arrays.stream(key).forEach(item -> this.functionMap.putIfAbsent(item, Criteria::is));
+ return this;
+ }
+
+ /**
+ * 批量导入规则
+ *
+ * @param criteriaDescriptors 规则集合
+ * @return 结果
+ */
+ public CriteriaBuilder with(List criteriaDescriptors) {
+ criteriaDescriptors.forEach(criteriaDescriptor ->
+ this.with(criteriaDescriptor.getKey(), criteriaDescriptor.getMapper()));
+ return this;
+ }
+
+ public Criteria build() {
+ if (!CollectionUtils.isEmpty(functionMap)) {
+ // 键集合
+ Set keySet = functionMap.keySet();
+ // 建立查询器
+ Criteria[] criteria = Arrays.stream(BeanUtils.getPropertyDescriptors(qo.getClass()))
+ .filter(propertyDescriptor -> keySet.contains(propertyDescriptor.getName()))
+ .map(propertyDescriptor -> {
+ try {
+ String key = propertyDescriptor.getName();
+ // 值
+ Object value = propertyDescriptor.getReadMethod().invoke(qo);
+ // 值非空予以过滤
+ if (!ObjectUtils.isEmpty(value)) {
+ String field = keyMapper.getOrDefault(key, key);
+ return functionMap.getOrDefault(propertyDescriptor.getName(), Criteria::is).apply(
+ Criteria.where(field), fixValue(field, value));
+ }
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ return null;
+ })
+ .filter(Objects::nonNull)
+ .toArray(Criteria[]::new);
+ return combine(criteria);
+ }
+ return null;
+ }
+
+ /**
+ * 修正查询最终值,主要是ObjectId
+ *
+ * @return 结果
+ */
+ @SuppressWarnings("unchecked")
+ private Object fixValue(String field, Object value) {
+ if (field.contains(".$id")) {
+ if (value instanceof Collection) {
+ Collection