java-通过反射实现比较两个对象不同的字段

33 篇文章 1 订阅

说明:代码中的Sring… param 为可拓展字段,可以理解为String[] param

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
* @description: 对比对象变化值的工具类
* @fileName: CompareObjectPropertyUtil.java
* @author: Sure
* @createAt: 2022/02/09 11:49
*/
@Slf4j
@Component
public class CompareDifferObjectInfo {
    /**
     * 注入字典查询接口
     */
    @Resource
    private DictCommonApi dictCommonApi;

    private final static String NO = "0";
    /**
     * 比较两个对象不同的属性并记录返回
     *
     * @param oldObj           旧对象
     * @param newObj           新对象
     * @param ignoreProperties 可忽略比的属性
     * @return 修改的内容
     */
    public <T> List<ModifiedPropertyInfo> getDifferentProperty(T oldObj, T newObj, String... ignoreProperties) {
        if (oldObj != null && newObj != null) {
            // 比较全部字段
            if (ignoreProperties == null || ignoreProperties.length > 0) {
                if (oldObj.equals(newObj)) {
                    return Collections.emptyList();
                }
            }
            List<PropertyModelInfo> oldObjectPropertyValue = getObjectPropertyValue(oldObj, ignoreProperties);
            if (!CollectionUtils.isEmpty(oldObjectPropertyValue)) {
                List<ModifiedPropertyInfo> modifiedPropertyInfos = new ArrayList<>(oldObjectPropertyValue.size());
                List<PropertyModelInfo> newObjectPropertyValue = getObjectPropertyValue(newObj, ignoreProperties);
                Map<String, Object> objectMap = new HashMap<>(newObjectPropertyValue.size());
                // 获取新对象所有属性值
                for (PropertyModelInfo propertyModelInfo : newObjectPropertyValue) {
                    String propertyName = propertyModelInfo.getPropertyName();
                    Object value = propertyModelInfo.getValue();
                    objectMap.put(propertyName, value);
                }
                for (PropertyModelInfo propertyModelInfo : oldObjectPropertyValue) {
                    String propertyName = propertyModelInfo.getPropertyName();
                    String propertyComment = propertyModelInfo.getPropertyComment();
                    Object value = propertyModelInfo.getValue();
                    if (objectMap.containsKey(propertyName)) {
                        Object newValue = objectMap.get(propertyName);
                        ModifiedPropertyInfo modifiedPropertyInfo = new ModifiedPropertyInfo();
                        if (value != null && newValue != null) {
                            if (!value.equals(newValue)) {
                                modifiedPropertyInfo.setPropertyName(propertyName);
                                modifiedPropertyInfo.setPropertyComment(propertyComment);
                                modifiedPropertyInfo.setOldValue(value);
                                modifiedPropertyInfo.setNewValue(newValue);
                                modifiedPropertyInfos.add(modifiedPropertyInfo);
                            }
                        } else if (isaBoolean(newValue == null, value != null, StringUtils.isBlank(value.toString()))
                                || (isaBoolean(value == null, newValue != null, StringUtils.isBlank(newValue.toString())))) {
                            modifiedPropertyInfo.setPropertyName(propertyName);
                            modifiedPropertyInfo.setPropertyComment(propertyComment);
                            modifiedPropertyInfo.setOldValue(value);
                            modifiedPropertyInfo.setNewValue(newValue);
                            modifiedPropertyInfos.add(modifiedPropertyInfo);
                        }
                    }
                }
                return modifiedPropertyInfos;
            }
        }
        return Collections.emptyList();
    }

    /**
     * 通过反射获取对象的属性名称、getter返回值类型、属性值等信息
     *
     * @param obj              对象
     * @param ignoreProperties 可忽略比对的属性
     * @return 修改的内容
     */
    public <T> List<PropertyModelInfo> getObjectPropertyValue(T obj, String... ignoreProperties) {
        if (obj != null) {
            Class<?> objClass = obj.getClass();
            PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(objClass);
            List<PropertyModelInfo> modelInfos = new ArrayList<>(propertyDescriptors.length);
            Field[] fields = objClass.getDeclaredFields();
            List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
            for (Field field : fields) {
                field.setAccessible(true);
                String fieldName = field.getName();
                if (ignoreList == null || !ignoreList.contains(fieldName)) {
                    PropertyModelInfo propertyModelInfo = new PropertyModelInfo();
                    propertyModelInfo.setPropertyName(fieldName);
                    propertyModelInfo.setReturnType(field.getType());
                    Object fieldValue = getFieldValueByName(fieldName, obj);
                    // 通过自定义注解拿到属性注释
                    if (field.isAnnotationPresent(PropertyName.class)) {
                        PropertyName annotation = field.getAnnotation(PropertyName.class);
                        propertyModelInfo.setPropertyComment(annotation.name());
                        // 如果是字典项,则将code转换成name
//                        Object finalFieldValue = fieldValue;
                        if (isaBoolean(!ObjectUtils.isEmpty(annotation.dictName()), !ObjectUtils.isEmpty(fieldValue), " ".equals(fieldValue))) {
                            if ("yesNo".equals(annotation.dictName())) {
                                fieldValue = NO.equals(fieldValue) ? "无" :"有";
                            }
                            if ("userrole".equals(annotation.dictName())) {
                                fieldValue = NO.equals(fieldValue) ? "角色" :"人";
                            }
//                            if (!ObjectUtils.isEmpty(annotation.idName()) && !ObjectUtils.isEmpty(annotation.valueName())) {
//                                List<Map<String, Object>> mapList = dictCommonApi.queryAll(annotation.dictName(), annotation.idName() + "," + annotation.valueName(), null, null);
//                                Map<Object, Object> objectMap = mapList.stream().collect(Collectors.toMap(p -> p.get(annotation.idName()).toString(), s -> s.get(annotation.valueName()),(a1,a2)->a2));
//                                if (ObjectUtils.isEmpty(objectMap.get(fieldValue.toString()))) {
//                                    fieldValue = fieldValue;
//                                }else {
//                                    fieldValue = objectMap.get(fieldValue.toString());
//                                }
//                            }
                        }
                    }
                    propertyModelInfo.setValue(fieldValue == null ? "" : fieldValue);
                    modelInfos.add(propertyModelInfo);
                }
            }
            return modelInfos;
        }
        return Collections.emptyList();
    }

    private static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(o, new Object[]{});
            return value;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 判断三个值
     */
    private boolean isaBoolean(boolean b, boolean b2, boolean blank) {
        return b && b2 && !blank;
    }

}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值