IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> java - 比对两个对象字段值,并且返回值不一致的字段名称 -> 正文阅读

[开发测试]java - 比对两个对象字段值,并且返回值不一致的字段名称

需求:

对比两个版本的详情,对出现修改的地方进行标注表示此处有修改。

PART 1:

改良自org.springframework.beans.BeanUtils下的copyProperties方法

	/**
     * 比较两个对象的不同字段
     * @return
     */
    public static List<String> checkDiffFiled(Object source, Object target){

        List<String> result = new ArrayList<>();

        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");

        Class<?> actualEditable = target.getClass();
        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);

        for (PropertyDescriptor targetPd : targetPds) {
            PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
            if (sourcePd != null) {
                //获取两个目标字段的read方法
                Method readTarget = targetPd.getReadMethod();
                Method readSource = sourcePd.getReadMethod();
                if (readTarget != null && readSource != null) {
                    ResolvableType sourceResolvableType = ResolvableType.forMethodReturnType(readSource);
                    ResolvableType targetResolvableType = ResolvableType.forMethodReturnType(readTarget);

                    // Ignore generic types in assignable check if either ResolvableType has unresolvable generics.
                    //比较两个字段类型值是否一致
                    boolean isAssignable =
                            (sourceResolvableType.hasUnresolvableGenerics() || targetResolvableType.hasUnresolvableGenerics() ?
                                    ClassUtils.isAssignable(readTarget.getReturnType(), readSource.getReturnType()) : targetResolvableType.isAssignableFrom(sourceResolvableType));

                    if (isAssignable) {
                        try {
                            if (!Modifier.isPublic(readSource.getDeclaringClass().getModifiers())) {
                                readSource.setAccessible(true);
                            }
                            Object value1 = readSource.invoke(source);
                            if (!Modifier.isPublic(readTarget.getDeclaringClass().getModifiers())) {
                                readTarget.setAccessible(true);
                            }
                            Object value2 = readTarget.invoke(target);
                            if (!Objects.equals(value1,value2))
                                result.add(targetPd.getName());
                        }
                        catch (Throwable ex) {
                            throw new FatalBeanException(
                                    "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
                        }
                    }
                }
            }
        }

        return result;
    }

PART 2:

在上一版结束后,拿去前端对接口开发了,随后前端同学提出对象下的子对象的值不一致无法识别到。思考了一下咱递归不就行了,递归条件是如果当前字段存在多个字段值就往下深入,如果只有一个字段值为啥要放在对象里呢!
递归的坑点肯定比较多,所以排除了一些字段的校验,否则会无限套娃。

/**
 * 校验Bean工具类
 */
public class CheckBeanUtil {

    /**
     * 比较两个对象的不同字段
     * @param source
     * @param target
     * @param pPath
     * @return
     */
    public static List<String> checkDiffFiled(Object source, Object target, @Nullable String pPath){

        List<String> result = new ArrayList<>();

        if (!StringUtils.hasText(pPath))
            pPath = "";

        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");

        Class<?> actualEditable = target.getClass();
        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);

        for (PropertyDescriptor targetPd : targetPds) {
            if (targetPd.getName().equals("class"))
                continue;
            PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
            if (sourcePd != null) {
                //获取两个目标字段的read方法
                Method readTarget = targetPd.getReadMethod();
                Method readSource = sourcePd.getReadMethod();
                if (readTarget != null && readSource != null) {
                    ResolvableType sourceResolvableType = ResolvableType.forMethodReturnType(readSource);
                    ResolvableType targetResolvableType = ResolvableType.forMethodReturnType(readTarget);

                    // Ignore generic types in assignable check if either ResolvableType has unresolvable generics.
                    //比较两个字段类型值是否一致
                    boolean isAssignable =
                            (sourceResolvableType.hasUnresolvableGenerics() || targetResolvableType.hasUnresolvableGenerics() ?
                                    ClassUtils.isAssignable(readTarget.getReturnType(), readSource.getReturnType()) : targetResolvableType.isAssignableFrom(sourceResolvableType));

                    if (isAssignable) {
                        try {
                            if (!Modifier.isPublic(readSource.getDeclaringClass().getModifiers())) {
                                readSource.setAccessible(true); //如果是私有化字段,开启允许访问
                            }
                            Object value1 = readSource.invoke(source);
                            if (!Modifier.isPublic(readTarget.getDeclaringClass().getModifiers())) {
                                readTarget.setAccessible(true); //如果是私有化字段,开启允许访问
                            }
                            Object value2 = readTarget.invoke(target);
                            if (Objects.nonNull(value1) && Objects.nonNull(value2) && checkType(value1) && getPropertyDescriptors(value1.getClass()).length > 1){
                                //如果存在多个字段,递归继续深入
                                result.addAll(checkDiffFiled(value1,value2,pPath + targetPd.getName() + "."));
                            }else if (!Objects.equals(value1,value2))
                                result.add(pPath + targetPd.getName());
                        }
                        catch (Throwable ex) {
                            throw new FatalBeanException(
                                    "Could not compaire property '" + targetPd.getName() + "' from source to target", ex);
                        }
                    }
                }
            }
        }

        return result;
    }

    //略过一些java对象
    private static boolean checkType(Object obj){
        if (obj instanceof String
                || obj instanceof LocalDateTime
                || obj instanceof JSONArray
            )
            return false;
        return true;
    }
}

Part3:

前端:你这JSON格式的字符串没有细化到每一行啊,我这干不了,,,,是不可能的,大哥你先放下刀好好说话,,,啊,,

啊,世界清静了

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:47:46  更:2022-04-09 18:48:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:18:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码