jinpengyong
2020-08-19 dad714704451fbcc04b48d4efcb460410e7a8aa0
src/main/java/com/moral/common/util/ExampleUtil.java
@@ -1,10 +1,13 @@
package com.moral.common.util;
import com.moral.common.bean.Constants;
import com.moral.common.bean.PageBean;
import lombok.extern.log4j.Log4j;
import tk.mybatis.mapper.entity.Example;
import java.beans.PropertyDescriptor;
import javax.validation.constraints.NotNull;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
@@ -12,72 +15,55 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Log4j
public class ExampleUtil {
    private final static String OR_SPLIT = "or\\|";
    private final static String CRITERIA_SPLIT = "\\|\\|\\|";
    private final static String CONDITION_SPLIT = "\\|\\|";
    private static Map<String, Method> criteriaMethodMap = null;
    private static void setOrderByClause(Example example,String orderByClause) throws UnsupportedEncodingException {
    private final static String SPLIT = "\\|";
    private final static String OR = "_OR";
    private final static String OR_SPLIT = OR+SPLIT;
    private final static String CRITERIA = "_CR";
    private final static String CRITERIA_SPLIT = CRITERIA+SPLIT;
    private final static String CONDITION = "_CO";
    private final static String CONDITION_SPLIT = CONDITION+SPLIT;
    private static Map<String, Method> criteriaMethodMap = new ConcurrentHashMap<>();
    private static void setOrderByClause(Example example,String orderByClause) throws UnsupportedEncodingException, NoSuchFieldException {
           orderByClause = URLDecoder.decode(orderByClause,"UTF-8");
           String[] orderBys = orderByClause.split(CRITERIA_SPLIT);
           for(String orderBy : orderBys){
               String[] items = orderBy.split(CONDITION_SPLIT);
               String property = items[0];
               String sort = items[1];
               if("asc".equals(sort)){
                   example.orderBy(property).asc();
               }else{
                   example.orderBy(property).desc();
               if(items.length == 2){
                   String property = items[0];
                   String sort = items[1];
                   if(isPropertyOfClass(example.getEntityClass(),property)){
                       if("asc".equals(sort)){
                           example.orderBy(property).asc();
                       }else{
                           example.orderBy(property).desc();
                       }
                   }
               }
           }
    }
    public static Example generateExample(Class clzz, PageBean page) {
    public static Example generateExample(Class clazz, PageBean page){
        return  generateExample(clazz,false,page);
    }
    public static Example generateExample(Class clazz, boolean isDelete, PageBean page) {
        Example example = null;
        try {
            String params = page.getQueryParams();
            String orderByClause = page.getOrderByClause();
            example = new Example(clzz);
            example = new Example(clazz);
            if(!StringUtils.isNullOrEmpty(orderByClause)){
                setOrderByClause(example,orderByClause);
            }
            if(StringUtils.isNullOrEmpty(params)){ return example;}
            params = URLDecoder.decode(params, "UTF-8");
            if (!StringUtils.isNullOrEmpty(params) && params.startsWith("or|")) {
                String[] criteria = params.trim().split(OR_SPLIT);
                for (String criterion : criteria) {
                    Example.Criteria criteriaOfExample = null;
                    if (!StringUtils.isNullOrEmpty(criterion)) {
                        String[] conditions = criterion.trim().split(CRITERIA_SPLIT);
                        for (String condition : conditions) {
                            if (!StringUtils.isNullOrEmpty(condition)) {
                                String[] conditionItems = condition.split(CONDITION_SPLIT);
                                if (conditionItems != null && conditionItems.length > 1) {
                                    //方法名
                                    String methodName = conditionItems[0];
                                    //属性名
                                    String propertyName = conditionItems[1];
                                    Method method = getMethod(methodName);
                                    if (method != null && isPropertyOfClass(clzz, propertyName)) {
                                        List values = new ArrayList<Object>();
                                        if (conditionItems.length > 2) {
                                            for (int index = 2; index < conditionItems.length; index++) {
                                                values.add(conditionItems[index]);
                                            }
                                        }
                                        //经过所有验证后,才产生 or 条件组
                                        if(criteriaOfExample == null){
                                            criteriaOfExample = example.or();
                                        }
                                        invokeMethod(criteriaOfExample,method,propertyName,values);
                                    }
                                }
                            }
                        }
                    }
                }
            if(!StringUtils.isNullOrEmpty(params)){
                params = URLDecoder.decode(params, "UTF-8");
                loadCriterias(example,params);
            }
            if(!isDelete) {
                addDeletesToExample(example,clazz);
            }
        } catch (Exception ex) {
            log.error(ex.getMessage());
@@ -85,54 +71,119 @@
        }
        return example;
    }
    private static void invokeMethod(Object obj, Method method,String propertyName,List values) throws InvocationTargetException, IllegalAccessException {
        int len = values.size();
        switch (len) {
            case 0:
                if(method.getParameterCount()==1) {
                    method.invoke(obj, propertyName);
                }
                break;
            case 1:
                if(method.getParameterCount()==2){
                    method.invoke(obj,propertyName,values.get(0));
                }
                break;
            //between 查询
            case 2:
                if(method.getParameterCount()==3){
                    method.invoke(obj,propertyName,values.toArray());
                }
                break;
            //in 查询
            default:
                if(method.getParameterCount()==2){
                method.invoke(obj,propertyName,values);
                }
                break;
    private static void loadCriterias(Example example,String params) throws InvocationTargetException, IllegalAccessException {
        if (params.startsWith(OR)) {
            String[] criteria = params.trim().split(OR_SPLIT);
            for (String criterion : criteria) {
                // criterion为null或""跳过
                if(StringUtils.isNullOrEmpty(criterion)) { continue;};
                Example.Criteria criteriaOfExample = example.or();
                loadConditions(example,criteriaOfExample,criterion);
            }
        }
    }
    ;
    private static boolean isPropertyOfClass(Class clzz, String propertyName) throws NoSuchFieldException {
        return clzz.getDeclaredField(propertyName) != null;
    }
    private static Method getMethod(String methodName) {
        if (criteriaMethodMap == null) {
            criteriaMethodMap = new HashMap<>();
            Method[] methods = Example.Criteria.class.getMethods();
            for (Method m : methods) {
                Method method = criteriaMethodMap.get(m.getName());
                //重载函数存储参数最长的
                if (method==null||m.getParameterTypes().length>method.getParameterTypes().length){
                    criteriaMethodMap.put(m.getName(),m);
    private static void loadConditions(Example example,Example.Criteria criteriaOfExample,String criterion) throws InvocationTargetException, IllegalAccessException {
        String[] conditions = criterion.trim().split(CRITERIA_SPLIT);
        for (String condition : conditions) {
            if (!StringUtils.isNullOrEmpty(condition)) {
                String[] conditionItems = condition.split(CONDITION_SPLIT);
                if (conditionItems != null && conditionItems.length > 1) {
                    //方法名
                    String methodName = conditionItems[0];
                    //属性名
                    String propertyName = conditionItems[1];
                    //参数列表
                    List values = new ArrayList<Object>();
                    if (conditionItems.length > 2) {
                        for (int index = 2; index < conditionItems.length; index++) {
                            values.add(conditionItems[index]);
                        }
                    }
                    Method method = getExampleMethod(methodName,values.size()+1);
                    if (method != null && (methodName.equals("andCondition")||isPropertyOfClass(example.getEntityClass(), propertyName))) {
                        invokeMethod(criteriaOfExample,method,propertyName,values);
                    } else {
                        log.warn(condition+"  can't be executed as condition");
                    }
                }
            }
        }
        return criteriaMethodMap.get(methodName);
    }
    private static boolean validatetParameters(@NotNull Method method,int len) {
        //前端传递propertyName参数为string类型
        return  method.getParameterCount() == (len+1) && method.getParameterTypes()[0].equals(String.class);
    }
    private static void invokeMethod(@NotNull Object obj,@NotNull Method method,@NotNull String propertyName,@NotNull List values) throws InvocationTargetException, IllegalAccessException {
        int len = values.size();
            switch (len) {
                case 0:
                    method.invoke(obj, propertyName);
                    break;
                case 1:
                    Object value = values.get(0) == "null" ? null : values.get(0);
                    method.invoke(obj, propertyName,value);
                    break;
                //between 查询
                case 2:
                    method.invoke(obj, propertyName, values.toArray());
                    break;
                //in 查询
                default:
                    method.invoke(obj, propertyName, values);
                    break;
            }
    }
    ;
    /**
     * 增加删除条件过滤
     * @param example
     */
    private static void addDeletesToExample(Example example,Class clzz){
        if(isPropertyOfClass(clzz,"isDelete")) {
            List<Example.Criteria> criteriaList = example.getOredCriteria();
            if(criteriaList!=null&&criteriaList.size()>0){
                for(Example.Criteria cri : criteriaList){
                    boolean isHasIsDelete = false;
                    for(Example.Criterion con : cri.getCriteria()){
                          if( con.getCondition().indexOf("is_delete") >-1) {
                              isHasIsDelete = true;
                              break;
                          }
                    }
                    if( !isHasIsDelete) {
                        cri.andNotEqualTo("isDelete", Constants.IS_DELETE_TRUE);
                    }
                }
            }else {
                example.or().andNotEqualTo("isDelete",Constants.IS_DELETE_TRUE);
            }
        }
    }
    private static boolean isPropertyOfClass(Class clzz, String propertyName){
        for(Field field : clzz.getDeclaredFields()) {
            if(field.getName().equals(propertyName)) {
                return  true;
            }
        }
        return false;
    }
    private static Method getExampleMethod(String methodName, int paramCount) {
        String criteriaMethodKey = methodName+"_"+String.valueOf(paramCount);
        Method methodTemp = criteriaMethodMap.get(criteriaMethodKey);
        if(methodTemp==null) {
            Method[] methods = Example.Criteria.class.getMethods();
            for (Method method : methods) {
                if(method.getName().equals(methodName)&&method.getParameterCount() == paramCount) {
                    criteriaMethodMap.put(criteriaMethodKey,method);
                    return method;
                }
            }
        }
        if(methodTemp==null || validatetParameters(methodTemp,paramCount)){
            return null;
        }
        return methodTemp;
    }
}