1、操作对象工具 MyBeanUtils
package com.nrxt.nms.mon.pt.cascade.utils;import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;/*** 操作对象工具*/
public class MyBeanUtils extends BeanUtils {private static final Logger logger = LoggerFactory.getLogger(BeanUtils.class);private static final String SERIAL_VERSION_UID = "serialVersionUID";private static final String INTEGER = "java.lang.Integer";private static final String STRING = "java.lang.String";/*** Copy properties.** @param source the source* @param target the target* @throws BeansException the beans exception*/public static void copyProperties(Object source, Object target) throws BeansException {copyProperties(source, target, null, (String[]) null);}private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties)throws BeansException {Assert.notNull(source, "Source must not be null");Assert.notNull(target, "Target must not be null");Class<?> actualEditable = target.getClass();if (editable != null) {if (!editable.isInstance(target)) {throw new IllegalArgumentException("Target class [" + target.getClass().getName()+ "] not assignable to Editable class [" + editable.getName() + "]");}actualEditable = editable;}PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);for (PropertyDescriptor targetPd : targetPds) {Method writeMethod = targetPd.getWriteMethod();if (writeMethod == null) {continue;}if (ignoreList == null || !ignoreList.contains(targetPd.getName())) {PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());if (sourcePd != null) {Method readMethod = sourcePd.getReadMethod();if (readMethod != null &&ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {try {if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {readMethod.setAccessible(true);}Object value = readMethod.invoke(source);// 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等if (value != null) {if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {writeMethod.setAccessible(true);}writeMethod.invoke(target, value);}} catch (Throwable ex) {throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", ex);}}}}}}/*** 复制对象** @param <T> the type parameter* @param entity the entity* @param targetCls the target cls* @return t t*/public static <T> T copyObject(Object entity, Class<? extends T> targetCls) {// 如果entity,直接返回nullif (entity == null) {return null;}Object target = null;try {target = targetCls.newInstance();copyProperties(entity, target);} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();}return (T) target;}/*** 复制对象** @param list the list* @param targetCls the target cls* @return list list*/public static <T> List<T> copyList(List list, Class<? extends T> targetCls) {List<T> resultList = new ArrayList();if (list != null && list.size() > 0) {for (Object entity : list) {resultList.add(copyObject(entity, targetCls));}}return resultList;}/*** java反射bean的get方法** @param objectClass the object class* @param fieldName the field name* @return get method*/@SuppressWarnings("unchecked")public static Method getGetMethod(Class objectClass, String fieldName) {if (objectClass != null && StringUtils.isNotBlank(fieldName)) {StringBuffer sb = new StringBuffer();sb.append("get");sb.append(fieldName.substring(0, 1).toUpperCase());sb.append(fieldName.substring(1));try {return objectClass.getMethod(sb.toString());} catch (NoSuchMethodException e) {e.printStackTrace();logger.error("error:{}", e);}}return null;}/*** java反射bean的set方法** @param objectClass the object class* @param fieldName the field name* @return set method*/@SuppressWarnings("unchecked")public static Method getSetMethod(Class objectClass, String fieldName) {try {Class[] parameterTypes = new Class[1];Field field = objectClass.getDeclaredField(fieldName);parameterTypes[0] = field.getType();StringBuffer sb = new StringBuffer();sb.append("set");sb.append(fieldName.substring(0, 1).toUpperCase());sb.append(fieldName.substring(1));Method method = objectClass.getMethod(sb.toString(), parameterTypes);return method;} catch (Exception e) {e.printStackTrace();logger.error("error:{}", e);}return null;}/*** 执行set方法** @param o 执行对象* @param fieldName 属性* @param value 值*/public static void invokeSet(Object o, String fieldName, Object value) {Method method = getSetMethod(o.getClass(), fieldName);if (method != null) {try {method.invoke(o, new Object[]{value});} catch (Exception e) {e.printStackTrace();logger.error("error:{}", e);}}}/*** Invoke set string int.** @param o the o* @param fieldName <br>* @param value the value* @return <br>* @throws <br>* @describe 这个函数主要用于将字符串和数字型分开 前台都是字符串 根据model类型转换 现在仅支持String int 不是这两个类型不做set函数<br>*/public static void invokeSetStringInt(Object o, String fieldName, String value) {Method method = getGetMethod(o.getClass(), fieldName);if (method != null) {String type = method.getReturnType().getName();if (INTEGER.equals(type)) {invokeSet(o, fieldName, (value == null) ? null : Integer.parseInt(value));} else if (STRING.equals(type)) {invokeSet(o, fieldName, value);} else {logger.error("set 函数不能设置Sting和int以外的函数,设置类型:" + type + ",方法:" + method.getName());}}}/*** 执行get方法** @param o 执行对象* @param fieldName 属性* @return the object*/public static Object invokeGet(Object o, String fieldName) {Method method = getGetMethod(o.getClass(), fieldName);if (method != null) {try {return method.invoke(o, new Object[0]);} catch (Exception e) {e.printStackTrace();logger.error("error:{}", e);}}return null;}/*** Invoke get string string.** @param o the o* @param fieldName the field name* @return <br>* @throws <br>* @describe 将返回值包装成String 如果是空则仍然保持空 <br>*/public static String invokeGetString(Object o, String fieldName) {Object obj = invokeGet(o, fieldName);return (obj == null) ? null : String.valueOf(obj);}/*** Merger obj object.** @param <T> 项目域对象如果为空,则直接返回产品域对象 项目域对象字段属性为空,则使用产品域覆盖项目域字段* @param parent 产品域对象* @param son 项目域对象* @param refClass class对象* @return the object*/public static <T> Object mergerObj(T parent, T son, Class<?> refClass) {logger.debug(">>>>>>>>>>>>>>>>>>>mergerObj");logger.debug("Product object:" + parent);logger.debug("Project object:" + son);Object obj = null;try {obj = refClass.newInstance();if (parent == null) {obj = son;} else if (son == null) {obj = parent;} else {for (Field field : refClass.getDeclaredFields()) {String fieldName = field.getName();if (SERIAL_VERSION_UID.equalsIgnoreCase(fieldName)) {continue;}Object value = invokeGet(son, fieldName);if (value == null) {value = invokeGet(parent, fieldName);}invokeSet(obj, fieldName, value);}}} catch (Exception e) {e.printStackTrace();logger.error("error:{}", e);;}logger.debug("Page object:" + obj);return obj;}/*** Merger obj object.** @param <T> the type parameter* @param parent the parent* @param son the son* @param refClassParent the ref class parent* @param refClassSon the ref class son* @return the object*/public static <T> Object mergerObj(T parent, T son, Class<?> refClassParent, Class<?> refClassSon) {return mergerObj(parent, son, refClassParent, refClassSon, null);}/*** Merger obj object.** @param <T> 父对象为空,则直接返回子对象 子对象为空,则将子对象域父对象相同的字段拷贝给obj 父对象与子对象都不为空,现将子对象的值拷贝给obj,在将子对象与父对象相同的字段拷贝给obj, <p/> 例如:比如指标与业务视图字段合并,则指标为父对象、业务视图字段为子对象 <p/> 变量命名有问题* @param parent 父对象* @param son 子对象* @param refClassParent 父class对象* @param refClassSon 子class对象* @param prefix 前缀* @return the object*/public static <T> Object mergerObj(T parent, T son, Class<?> refClassParent, Class<?> refClassSon, String prefix) {logger.debug(">>>>>>>>>>>>>>>>>>>mergerObj");logger.debug("Parent object:" + parent);logger.debug("Son object:" + son);Map<String, String> publicFieldMap = new HashMap<String, String>(16);Object obj = null;try {/*** 比较父class对象与子class对象,找出字段相同的字段*/for (Field pField : refClassParent.getDeclaredFields()) {String pFieldName = pField.getName();for (Field sField : refClassSon.getDeclaredFields()) {String sFieldName = sField.getName();if (sFieldName.equals(pFieldName)) {publicFieldMap.put(pFieldName, sFieldName);break;} else if (prefix != null && sFieldName.equals(prefix + pFieldName)) {publicFieldMap.put(pFieldName, sFieldName);break;}}}obj = refClassSon.newInstance();//父对象为空,直接返回父对象给objif (parent == null) {obj = son;} else//子对象为空,将父对象中与子对象中相同字段的值复制给objif (son == null) {for (Map.Entry<String, String> entry : publicFieldMap.entrySet()) {String pFieldName = entry.getKey();String sFieldName = entry.getValue();if (SERIAL_VERSION_UID.equalsIgnoreCase(sFieldName)) {continue;}Object value = invokeGet(parent, sFieldName);invokeSet(obj, sFieldName, value);}} else {//先将子对象拷贝给objfor (Field field : refClassSon.getDeclaredFields()) {String fieldName = field.getName();if (SERIAL_VERSION_UID.equalsIgnoreCase(fieldName)) {continue;}Object value = invokeGet(son, fieldName);invokeSet(obj, fieldName, value);}//将相同字段的值拷贝给objfor (Map.Entry<String, String> entry : publicFieldMap.entrySet()) {String pFieldName = entry.getKey();String sFieldName = entry.getValue();if (SERIAL_VERSION_UID.equalsIgnoreCase(sFieldName)) {continue;}Object value = invokeGet(son, sFieldName);if (null == value || "".equals(value)) {value = invokeGet(parent, pFieldName);}invokeSet(obj, sFieldName, value);}}} catch (Exception e) {e.printStackTrace();logger.error("error:{}", e);;}logger.debug("Merge object:" + obj);return obj;}/*** Division obj t.** @param <T> the type parameter* @param parent 父对象* @param son 子对象* @param newSon 新的子对象* @param refClass class对象* @return T t*/public static <T> T divisionObj(T parent, T son, T newSon, Class<?> refClass) {logger.debug(">>>>>>>>>>>>>>>>>>>divisionObj");logger.debug("Product object:" + parent);logger.debug("Project object:" + son);logger.debug("Page object:" + newSon);for (Field field : refClass.getDeclaredFields()) {String filedName = field.getName();if (SERIAL_VERSION_UID.equalsIgnoreCase(filedName)) {continue;}/*项目域不存在,则说明该元素只是项目化没有修改,表里面不存在*/Object valueSon = (son == null) ? null : invokeGet(son, filedName);/*子对象的对应的属性为空,则继承与产品域的属性,如果没有修改则继续继承*/if (valueSon == null) {Object valueNewSon = invokeGet(newSon, filedName);Object valueParent = invokeGet(parent, filedName);if (valueParent != null && valueParent.equals(valueNewSon)) {invokeSet(newSon, filedName, null);}}}logger.debug("New object:" + newSon);return newSon;}/*** 比较产品域对象、项目域对象、页面对象,返回最后需要插入数据库中的对象** @param <T> the type parameter* @param parent 父对象* @param son 子对象* @param newSon 新的子对象* @param refClass class对象* @param excludeFields 不需要比较字段的列表* @return T t*/public static <T> T divisionObj(T parent, T son, T newSon, Class<?> refClass, String... excludeFields) {logger.debug(">>>>>>>>>>>>>>>>>>>divisionObj");logger.debug("Product object:" + parent);logger.debug("Project object:" + son);logger.debug("Page object:" + newSon);logger.debug("ExcludeFields:" + excludeFields);for (Field field : refClass.getDeclaredFields()) {String filedName = field.getName();if (SERIAL_VERSION_UID.equalsIgnoreCase(filedName)) {continue;}//排除不需要比较的字段if (Arrays.asList(excludeFields).contains(filedName)) {continue;}/*项目域不存在,则说明该元素只是项目化没有修改,表里面不存在*/Object valueSon = (son == null) ? null : invokeGet(son, filedName);/*子对象的对应的属性为空,则继承与产品域的属性,如果没有修改则继续继承*/if (valueSon == null) {Object valueNewSon = invokeGet(newSon, filedName);Object valueParent = invokeGet(parent, filedName);if (valueParent != null && valueParent.equals(valueNewSon)) {invokeSet(newSon, filedName, null);}}}logger.debug("New object:" + newSon);return newSon;}/*** 应用场景,产品域字段列表跟项目域字段列表合并,* 以keyName作为主键,* 相同的keyName,则使用项目域的覆盖产品域的** @param <T> the type parameter* @param parentList 父域列表* @param sonList 子域列表* @param keyName 主键* @return list list*/public static <T> List<T> mergerList(List<T> parentList, List<T> sonList, String keyName) {logger.debug(">>>>>>>>>>>>>>>>>>>mergerObj");logger.debug("Product object list:" + parentList);logger.debug("Project object list:" + sonList);logger.debug("keyName :" + keyName);List<T> resultList = new ArrayList<T>();Map<Object, T> map = new HashMap<Object, T>(16);if (parentList == null) {resultList.addAll(sonList);return resultList;}if (sonList == null) {resultList.addAll(parentList);return resultList;}resultList.addAll(parentList);for (T obj : parentList) {Object keyFieldName = invokeGet(obj, keyName);map.put(keyFieldName, obj);}int size = sonList.size();for (int i = 0; i < size; i++) {Object keyFieldName = invokeGet(sonList.get(i), keyName);if (map.containsKey(keyFieldName)) {resultList.remove(map.get(keyFieldName));resultList.add(i, sonList.get(i));} else {resultList.add(sonList.get(i));}}logger.debug("Page object list:" + sonList);return resultList;}/*** Get all field name string [ ].** @param <T> the type parameter* @param refClass <br>* @return <br>* @throws <br>* @describe 返回dto的所有属性字段名称 返回其中所有字段(除serialVersionUID之外) 可以用于设置值 <br>*/public static <T> String[] getAllFieldName(Class<?> refClass) {Field[] allField = refClass.getDeclaredFields();List<String> allFieldList = new ArrayList<String>();for (int i = 0, j = 0; i < allField.length; i++) {String filedName = allField[i].getName();if (!SERIAL_VERSION_UID.equalsIgnoreCase(filedName)) {allFieldList.add(filedName);}}return allFieldList.toArray(new String[allFieldList.size()]);}/*** Get all field field [ ].** @param <T> the type parameter* @param refClass <br>* @return <br>* @throws <br>* @describe 返回dto的所有Field字段 返回其中所有字段(除serialVersionUID之外) 可以用于设置值 <br>*/public static <T> Field[] getAllField(Class<?> refClass) {Field[] allField = refClass.getDeclaredFields();List<Field> allFieldList = new ArrayList<Field>();for (int i = 0, j = 0; i < allField.length; i++) {if (!SERIAL_VERSION_UID.equalsIgnoreCase(allField[i].getName())) {allFieldList.add(allField[i]);}}return allFieldList.toArray(new Field[allFieldList.size()]);}/*** 获取指定字段名称查找在class中的对应的Field对象(包括查找父类)** @param clazz 指定的class* @param fieldName 字段名称* @return Field对象 class field*/public static Field getClassField(Class clazz, String fieldName) {if (Object.class.getName().equals(clazz.getName())) {return null;}Field[] declaredFields = clazz.getDeclaredFields();for (Field field : declaredFields) {if (field.getName().equals(fieldName)) {return field;}}Class superClass = clazz.getSuperclass();if (superClass != null) {// 简单的递归一下return getClassField(superClass, fieldName);}return null;}/*** 求ls对ls2的差集,即ls中有,但ls2中没有的** @param ls the ls* @param ls2 the ls 2* @return list list*/public static List diff(List ls, List ls2) {List list = new ArrayList(Arrays.asList(new Object[ls.size()]));Collections.copy(list, ls);list.removeAll(ls2);return list;}/*** 求2个集合的交集** @param ls the ls* @param ls2 the ls 2* @return list list*/public static List intersect(List ls, List ls2) {List list = new ArrayList(Arrays.asList(new Object[ls.size()]));Collections.copy(list, ls);list.retainAll(ls2);return list;}/*** 求2个集合的并集** @param ls the ls* @param ls2 the ls 2* @return list list*/public static List union(List ls, List ls2) {List list = new ArrayList(Arrays.asList(new Object[ls.size()]));//将ls的值拷贝一份到list中Collections.copy(list, ls);list.removeAll(ls2);list.addAll(ls2);return list;}
}
2、实体类
package com.nrxt.nms.mon.pt.cascade.entity;import lombok.Data;import javax.persistence.Column;@Data
public class NmsAppDO {@Column(name = "CI_ID")String ciId;@Column(name = "CI_NAME")String ciName;@Column(name = "APPID")String appId;@Column(name = "BGCODE")String bgCode;@Column(name = "PROVID")String provId;@Column(name = "APPRATE")String appRate;@Column(name = "CLOUDFLAG")String cloudFlag;@Column(name = "OM_APP")String omApp;@Column(name = "SHORT_NAME")String shortName;@Column(name = "PUSH_TYPE")String pushType;@Column(name = "NETREGION")String netregion;@Column(name = "REPAIR_STATE")String repairState;@Column(name = "RUN_USER_TEL")String runUserTel;@Column(name = "SYSTEM_TYPE")String systemType;@Column(name = "IS_MONITOR")String isMonitor;@Column(name = "IS_APPFUNCINST")String isAppfuncinst;@Column(name = "IS_APMSERVICE")String isApmservice;@Column(name = "RUN_STATUS")String runStatus;@Overridepublic String toString() {return String.format("BGCODE=%s,CI_ID=%s,APPID=%s", bgCode, ciId, appId);}
}
package com.nrxt.nms.mon.pt.cascade.entity;import com.nrxt.nms.mon.pt.cascade.utils.DateUtils;
import lombok.Data;import javax.persistence.Column;@Data
public class NmsAppMonitorDO {public NmsAppMonitorDO(){this.monitorStatus = "0";this.deletedFlag = "N";this.createdAt = DateUtils.getLocalDateTime();this.updatedAt = DateUtils.getLocalDateTime();}@Column(name = "CI_ID")private String ciId;@Column(name = "APP_ID")private String appId;@Column(name = "APP_NAME")private String ciName;@Column(name = "APP_SHORT_NAME")private String shortName;@Column(name = "APP_RATE")private String appRate;@Column(name = "PUSH_TYPE")private String pushType;@Column(name = "NETREGION")private String netregion;@Column(name = "RUN_STATUS")private String runStatus;@Column(name = "MONITOR_STATUS")private String monitorStatus;@Column(name = "DELETED_FLAG")private String deletedFlag;@Column(name = "CREATED_AT")private String createdAt;@Column(name = "UPDATED_AT")private String updatedAt;@Column(name = "TOTAL")private Integer total;}
3、工具类使用
List<NmsAppMonitorDO> nmsAppMonitorDOList = MyBeanUtils.copyList(nmsAppDOList,NmsAppMonitorDO.class);