复杂对象比较工具类

会记录变更前/后的值,变更字段的属性名,变更字段中午名称
先看效果:
todo:纯为了实现需求效果,代码优化空间还很大

/**
 * 对象比较工具类
 */
@Slf4j
public class ClassInstanceCompareUtil {

    /**
     * 对象比较
     * @param source 源对象
     * @param target 目标对象
     * @return 比较结果对象
     */
    public static CompareResultVo compareObject(Object source, Object target) {
        CompareResultVo compareResultVo = new CompareResultVo();
        if (source == null && target == null) {
            return compareResultVo;
        }
        if (source == null || target == null) {
            return compareResultVo;
        }
        Class<?> oldClazz = source.getClass();
        Class<?> newClazz = target.getClass();
        if (oldClazz != newClazz) {
            return compareResultVo;
        }
        List<Field> fields = Arrays.stream(oldClazz.getDeclaredFields()).collect(Collectors.toList());
        List<LabelValueResultVo> modifyInfoList = new ArrayList<>();
        List<String> modifyFieldList = new ArrayList<>();

        for (Field field : fields) {
            try {
                if (isSerialVersionUIDField(field.getName())) {
                    continue;
                }
                fieldCheck(field, source, target, modifyInfoList,modifyFieldList);
            } catch (Exception e) {
                log.info("field.error.fieldName:{},errorMsg:{}", field.getName(), e.getMessage(), e);
            }
        }
        compareResultVo.setModifyInfoList(modifyInfoList);
        compareResultVo.setModifyFieldList(modifyFieldList);
        return compareResultVo;
    }

    /**
     * 比较两个对象的指定字段是否相等
     * @param field 字段
     * @param source 源对象
     * @param target 目标对象
     * @param modifyInfoList 修改列表
     * @throws Exception 异常
     */
    public static void fieldCheck(Field field, Object source, Object target, List<LabelValueResultVo> modifyInfoList,List<String> modifyFieldList) throws Exception {
        field.setAccessible(true);
        NeedCompare needCompare = field.getAnnotation(NeedCompare.class);
        if (needCompare == null) {
            return;
        }
        Class<?> type = field.getType();
        if (isBaseType(type)) {
            Object o1 = field.get(source);
            Object o2 = field.get(target);
            if (Objects.isNull(o1) && Objects.isNull(o2)){
                return;
            }
            if (Objects.isNull(o1)){
                if (type == String.class){
                   if (StringUtils.isBlank(o2.toString())){
                       return;
                   }
                }
                if (type == Date.class){
                    String s = DateUtil.dateToStr((Date) o2);
                    o2 = DateUtil.strToDate(s);

                }
            }
            if (Objects.isNull(o2)){
                if (type == String.class){
                    if (StringUtils.isBlank(o1.toString())){
                        return;
                    }
                }
                if (type == Date.class){
                    String s = DateUtil.dateToStr((Date) o1);
                    o1 = DateUtil.strToDate(s);
                }
            }
            if (!Objects.equals(o1, o2)) {
                try {
                    ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
                    if (apiModelProperty != null) {
                        LabelValueResultVo labelValueVo = new LabelValueResultVo();
                        labelValueVo.setLabel(apiModelProperty.value());
                        ChangeVO changeVO = new ChangeVO();
                        changeVO.setBefore(Objects.isNull(field.get(source)) ? "" : field.get(source));
                        changeVO.setAfter(Objects.isNull(field.get(target)) ? "" : field.get(target));
                        labelValueVo.setValue(changeVO);
                        modifyInfoList.add(labelValueVo);
                        modifyFieldList.add(field.getName());
                    }
                } catch (Exception e) {
                    log.info("field.error.fieldName:{},errorMsg:{}", field.getName(), e.getMessage(), e);
                }
            }
        } else if (isCollection(type)) {
            //集合比较
            List o1 = (List) field.get(source);
            List o2 = (List) field.get(target);
            if (CollectionUtils.isEmpty(o1) && CollectionUtils.isEmpty(o2)){
                return;
            }
            ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
            LabelValueResultVo labelValueVo = new LabelValueResultVo();
            labelValueVo.setLabel(apiModelProperty.value());
            if (o1.size() == o2.size() || o1.size() > o2.size()) {
                // 创建一个临时列表用于存放相同的元素
                List<Object> newList = new ArrayList<>(o1);
                newList.retainAll(o2); // 保留 o1 和 o2 中共有的元素
                // 从 o1 和 o2 中删除相同的元素
                o1.removeAll(newList);
                o2.removeAll(newList);
                if (CollectionUtils.isNotEmpty(o1) || CollectionUtils.isNotEmpty(o2)) {
                    ChangeVO changeVO = new ChangeVO();
                    List<LabelValueResultVo> labelValueResultVoList = getListField(o1,apiModelProperty.value());
                    List<LabelValueResultVo> labelValueResultVoList1 = getListField(o2,apiModelProperty.value());
                    changeVO.setBefore(labelValueResultVoList);
                    changeVO.setAfter(labelValueResultVoList1);
                    labelValueVo.setValue(changeVO);
                    modifyInfoList.add(labelValueVo);
                    modifyFieldList.add(field.getName());
                }
            }
            if (o1.size() < o2.size()) {
                // 创建一个临时列表用于存放相同的元素
                List<Object> newList = new ArrayList<>(o2);
                newList.retainAll(o1); // 保留 o1 和 o2 中共有的元素
                // 从 o1 和 o2 中删除相同的元素
                o1.removeAll(newList);
                o2.removeAll(newList);
                if (CollectionUtils.isNotEmpty(o1) || CollectionUtils.isNotEmpty(o2)) {
                    ChangeVO changeVO = new ChangeVO();
                    List<LabelValueResultVo> labelValueResultVoList = getListField(o1, apiModelProperty.value());
                    List<LabelValueResultVo> labelValueResultVoList1 = getListField(o2,apiModelProperty.value());
                    changeVO.setBefore(labelValueResultVoList);
                    changeVO.setAfter(labelValueResultVoList1);
                    labelValueVo.setValue(changeVO);
                    modifyInfoList.add(labelValueVo);
                    modifyFieldList.add(field.getName());
                }
            }
        } else {
            Object o1 = field.get(source);
            Object o2 = field.get(target);
            if (o1 == null && o2 == null) {
                return;
            }
            List<Field> fields = Arrays.stream(field.get(source).getClass().getDeclaredFields()).collect(Collectors.toList());
            for (Field field1 : fields) {
                if (isSerialVersionUIDField(field1.getName())) {
                    continue;
                }
                fieldCheck(field1, o1, o2, modifyInfoList,modifyFieldList);
            }
        }
    }


    /**
     * 判断给定的字段名是否为serialVersionUID字段
     * @param fieldName 字段名
     * @return 如果字段名为"serialVersionUID",则返回true,否则返回false
     */
    public static boolean isSerialVersionUIDField(String fieldName){
        return "serialVersionUID".equals(fieldName);
    }


    public static List<LabelValueResultVo> getListField(List list,String value) {
        List<LabelValueResultVo> resultVos = new ArrayList<>();
        try {
            for (int i = 0; i < list.size(); i++) {
                int x= i+1;
                LabelValueResultVo resultVo = new LabelValueResultVo();
                List<LabelValueResultVo> newFesultVos = new ArrayList<>();
                resultVo.setLabel(value+x);
                List<Field> oldFields = Arrays.stream(list.get(i).getClass().getDeclaredFields()).collect(Collectors.toList());
                for (Field field1 : oldFields) {
                    field1.setAccessible(true);
                    if (isSerialVersionUIDField(field1.getName())) {
                        continue;
                    }
                    ApiModelProperty newApiModelProperty = field1.getAnnotation(ApiModelProperty.class);
                    if (newApiModelProperty == null) {
                        continue;
                    }
                    NeedCompare newNeedCompare = field1.getAnnotation(NeedCompare.class);
                    if (newNeedCompare == null) {
                        continue;
                    }
                    if (Objects.isNull(field1.get(list.get(i)))) {
                        continue;
                    }
                    LabelValueResultVo labelValueResultVo = new LabelValueResultVo();
                    labelValueResultVo.setLabel(newApiModelProperty.value());
                    labelValueResultVo.setValue(field1.get(list.get(i)));
                    newFesultVos.add(labelValueResultVo);
                }
                resultVo.setValue(newFesultVos);
                resultVos.add(resultVo);
                //resultVos.addAll(labelValueResultVoList);
            }

        } catch (Exception e) {
            log.info("getListField.error,msg:{}", e.getMessage(), e);
        }
        return resultVos;
    }

    /**
     * 是否是基本数据类型
     */
    public static boolean isBaseType(Class<?> clazz) {
        return clazz.isPrimitive() || clazz == String.class || clazz == Character.class || clazz == Boolean.class || clazz == Byte.class || clazz == Short.class || clazz == Integer.class || clazz == Long.class || clazz == Float.class || clazz == Double.class || clazz == BigInteger.class || clazz == BigDecimal.class;
    }


   
/**
 * 标注在字段的注解,表示需要进行比较
 */
@Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedCompare {
}
@Data
public class CompareResultVo {
    /**
     * 变更内容
     */
    private List<LabelValueResultVo> modifyInfoList;

    /**
     * 变更的字段属性名称
     */
    private List<String> modifyFieldList;
}
@Data
public class LabelValueResultVo {

    @ApiModelProperty("展示内容")
    private Object label;

    @ApiModelProperty("值")
    private Object value;
}
@Data
public class ChangeVO {

    private Object before;

    private Object after;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值