java中兩個物件間的屬性值複製,比較,轉為map方法實現

Franson發表於2016-07-15
package com.franson.study.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.avalon.framework.service.ServiceException;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class BeanUtil {

    private static Log log = LogFactory.getLog(BeanUtil.class);

    /**
     * 兩物件之間的拷貝(在目標物件中存在的所有set方法,如果在源物件中存在對應的get方法,不管源物件的get方法的返回值是否為null,都進行拷貝)
     * 僅拷貝方法名及方法返回型別完全一樣的屬性值
     * @param desc     目標物件
     * @param orig     源物件
     * @param excludeFields 不拷貝的field(多個用逗號隔開)
     */
    public static void copyPropertiesNotForce(Object desc, Object orig,String excludeFields) {
        copyPropertiesNotForce(desc, orig, excludeFields, true);
    }
    /**
     * 兩物件之間的拷貝(在目標物件中存在的所有set方法,如果在源物件中存在對應的get方法,不管源物件的get方法的返回值是否為null,都進行拷貝)
     * 僅拷貝方法名及方法返回型別完全一樣的屬性值
     * @param desc     目標物件
     * @param orig     源物件
     * @param excludeFields     源物件
     * @param isCopyNull     為null的屬性是否拷貝(true拷貝null屬性;false不拷貝null屬性)
     * @param excludeFields 不拷貝的field(多個用逗號隔開)
     */
    public static void copyPropertiesNotForce(Object desc, Object orig,String excludeFields, boolean isCopyNull) {
        Class<?> origClass = orig.getClass();
        Class<?> descClass = desc.getClass();

        Method[] descMethods = descClass.getMethods();
        Method[] origMethods = origClass.getMethods();

        boolean needExclude = false;                    //是否需要過濾部分欄位
        if(!StringUtil.isEmpty(excludeFields)){
            needExclude = true;
            excludeFields = "," + excludeFields.toLowerCase() + ",";
        }
        
        Map<String,Method> methodMap = new HashMap<String,Method>();
        for (int i = 0; i < origMethods.length; i++) {
            Method method = origMethods[i];
            String methodName = method.getName();
            if (!methodName.equals("getClass")
                    && methodName.startsWith("get")
                    && (method.getParameterTypes() == null || method
                            .getParameterTypes().length == 0)) {
                if(needExclude && excludeFields.indexOf(methodName.substring(3).toLowerCase()) > -1){
                    continue;
                }
                methodMap.put(methodName, method);
            }
        }
        for (int i = 0; i < descMethods.length; i++) {
            Method method = descMethods[i];
            String methodName = method.getName();
            if (!methodName.equals("getClass")
                    && methodName.startsWith("get")
                    && (method.getParameterTypes() == null || method
                            .getParameterTypes().length == 0)) {
                if (methodMap.containsKey(methodName)) {
                    Method origMethod = (Method) methodMap.get(methodName);
                    try {
                        if (method.getReturnType().equals(
                                origMethod.getReturnType())) {
                            Object returnObj = origMethod.invoke(orig, null);
                            if(!isCopyNull && returnObj == null){
                                continue;
                            }
                            
                            String field = methodName.substring(3);
                            String setMethodName = "set" + field;
                            Method setMethod = descClass.getMethod(
                                    setMethodName, new Class[] { method
                                            .getReturnType() });
                            setMethod.invoke(desc, new Object[] { returnObj });
                        }
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
    /**
     * 兩物件之間的拷貝(在目標物件中存在的所有set方法,如果在源物件中存在對應的get方法,不管源物件的get方法的返回值是否為null,都進行拷貝)
     * 僅拷貝方法名及方法返回型別完全一樣的屬性值
     * @param desc     目標物件
     * @param orig     源物件
     */
    public static void copyPropertiesNotForce(Object desc, Object orig) {
        copyPropertiesNotForce(desc, orig, null);
    }
    
    /**
     * 兩物件之間的拷貝(在目標物件中存在的所有set方法,如果在源物件中存在對應的get方法,源物件的get方法的返回值為null的不拷貝)
     * 僅拷貝方法名及方法返回型別完全一樣的屬性值
     * @param desc     目標物件
     * @param orig     源物件
     * @param excludeFields 不拷貝的field(多個用逗號隔開)
     */
    public static void copyPropertiesNotNull(Object desc, Object orig) {
        copyPropertiesNotForce(desc, orig, null, false);
    }
    
    public static void copyPropertiesNotNull(Object desc, Object orig,String excludeFields) {
        copyPropertiesNotForce(desc, orig, excludeFields, false);
    }
    /**
     * 判斷兩個物件的所有相同屬性值是否相等,注意盡是比較相同的屬性,對於A物件屬性比B物件屬性多,如果相同屬性值相同,則返回為true
     * @param desc
     * @param orig
     * @return 相等返回true,否則返回false
     * @throws CrmBaseException
     */
public static boolean isEqualBeanProperties(Object desc, Object orig) throws CrmBaseException {
        String result= compareBeanProperties(desc,orig);
        if(result.equals("[]"))
            return true;
        return false;
}
    /**
     * 比較兩個Bean相同欄位的值(以源物件的值為基準,json串中顯示目標物件中的值)【僅比較可轉換為string的型別】
     * @param desc 目標物件
     * @param orig 源物件        
     * @return String 不一致的欄位json串
     * @throws  ServiceException
     */
    public static String compareBeanProperties(Object desc, Object orig)
            throws CrmBaseException {
        Map<String, Object> map = new HashMap<String, Object>();
        Class<?> origClass = orig.getClass();
        Class<?> descClass = desc.getClass();

        Method[] descMethods = descClass.getMethods();
        Method[] origMethods = origClass.getMethods();

        Map<String,Method> methodMap = new HashMap<String,Method>();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < origMethods.length; i++) {
            Method method = origMethods[i];
            String methodName = method.getName();
            if (!methodName.equals("getClass")
                    && methodName.startsWith("get")
                    && (method.getParameterTypes() == null || method
                            .getParameterTypes().length == 0)) {
                methodMap.put(methodName, method);
            }
        }
        for (int i = 0; i < descMethods.length; i++) {
            Method method = descMethods[i];
            String methodName = method.getName();
            if (!methodName.equals("getClass")
                    && methodName.startsWith("get")
                    && (method.getParameterTypes() == null || method
                            .getParameterTypes().length == 0)) {
                if (methodMap.containsKey(methodName)) {
                    Method origMethod = (Method) methodMap.get(methodName);
                    try {
                        if (method.getReturnType().equals(
                                origMethod.getReturnType())) {
                            Object origObj = origMethod.invoke(orig, null);
                            origObj = origObj == null ? "" : origObj;

                            Method descMethod = descClass.getMethod(methodName,
                                    null);
                            Object descObj = descMethod.invoke(desc, null);
                            descObj = descObj == null ? "" : descObj;

                            if (!origObj.equals(descObj)) {
                                map.put(methodName.substring(3), descObj);
                                sb.append(",{'field':'");
                                sb.append(methodName.substring(3));
                                sb.append("','msg':'");
                                sb.append(descObj.toString().replaceAll("\'",
                                        ""));
                                sb.append("'}");
                            }
                        }
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        String str = "[";
        if (sb.length() > 0) {
            str += sb.substring(1);
        }
        return str + "]";
    }

    /**
     * bean轉Map
     * @param bean
     * @return
     */
    public static Map beanToMap(Object bean){
         //return bean2Map(bean);
        return objectToMap(bean);
    }

      
    /**
     * 通過欄位名獲取方法陣列
     * @param beanClass            Class<?>
     * @param fieldNameArray    要輸出的所有欄位名陣列
     * @return                Method[]
     */
    public static Method[] getMethods(Class<?> beanClass,String[] fieldNameArray){
        Method[] methodArray = new Method[fieldNameArray.length];
        
        String methodName;
        String fieldName;
        for (int i=0;i<fieldNameArray.length;i++) {
            Method method = null;
            fieldName = fieldNameArray[i];
            methodName = fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
            try {
                method = beanClass.getMethod("get"+methodName, null);
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                try {
                    method = beanClass.getMethod("is"+methodName, null);
                } catch (SecurityException e1) {
                    e1.printStackTrace();
                } catch (NoSuchMethodException e1) {
                    e1.printStackTrace();
                }
            }
            methodArray[i] = method;
        }
        
        return methodArray;
    }
    
    private static <K, V> Map<K, V> bean2Map(Object javaBean) {
        Map<K, V> ret = new HashMap<K, V>();
        try {
            Method[] methods = javaBean.getClass().getDeclaredMethods();
            for (Method method : methods) {
                if (method.getName().startsWith("get")) {
                    String field = method.getName();
                    field = field.substring(field.indexOf("get") + 3);
                    field = field.toLowerCase().charAt(0) + field.substring(1);
                    Object value = method.invoke(javaBean, (Object[]) null);
                    ret.put((K) field, (V) (null == value ? "" : value));
                }
            }
        } catch (Exception e) {
        }
        return ret;
    }
    
     public static Map objectToMap(Object o){
        return objectToMap(o, "");
      }
    
     private static Map objectToMap(Object o, String prefix)
      {
        Map ret = new HashMap();
        if (o == null)
          return ret;
        try {
          Map objDesc = PropertyUtils.describe(o);

          prefix = (!("".equals(prefix))) ? prefix + "." : "";
          for (Iterator it = objDesc.keySet().iterator(); it.hasNext(); ) {
            String key = it.next().toString();
            Object val = objDesc.get(key);
            if ((val != null) && (val instanceof CrmValueObject) && (!(o.equals(val))))
            {
              ret.putAll(objectToMap(val, prefix + key)); break;
            }
            ret.put(prefix + key, val);
          }
        } catch (Exception e) {
            e.printStackTrace();
          //logger.error(e);
        }
        //logger.debug("Object " + o + " convert to map: " + ret);
        return ret;
      }
     
    public static Map objectToMap(List fieldNameList, Object object)
      {
        Map ret = new HashMap();
        for (Iterator it = fieldNameList.iterator(); it.hasNext(); ) {
          String fieldName = (String)it.next();
          String[] fs = fieldName.split(quote("."));
          try {
            Object o = object;
            for (int i = 0; i < fs.length; ++i) {
              Map objDesc = PropertyUtils.describe(o);
              o = objDesc.get(fs[i]);
              if (o == null)
                break;
            }
            ret.put(fieldName, o);
          } catch (Exception e) {
              e.printStackTrace();
            //logger.error(e);
          }
        }
        return ret;
      }
    
    public static String quote(String s)
      {
        int slashEIndex = s.indexOf("\\E");
        if (slashEIndex == -1)
          return "\\Q" + s + "\\E";

        StringBuffer sb = new StringBuffer(s.length() * 2);
        sb.append("\\Q");
        slashEIndex = 0;
        int current = 0;
        while ((slashEIndex = s.indexOf("\\E", current)) != -1) {
          sb.append(s.substring(current, slashEIndex));
          current = slashEIndex + 2;
          sb.append("\\E\\\\E\\Q");
        }
        sb.append(s.substring(current, s.length()));
        sb.append("\\E");
        return sb.toString();
      }
}

 

相關文章