diff --git a/ClazzDiff.java b/ClazzDiff.java new file mode 100644 index 0000000..488604c --- /dev/null +++ b/ClazzDiff.java @@ -0,0 +1,206 @@ +package com.utils; // 声明该Java类所在的包为com.utils + +import com.annotation.ColumnInfo; // 导入自定义的ColumnInfo注解,用于获取字段相关信息 +import org.apache.tools.ant.util.DateUtils; // 导入Apache Ant工具集中用于处理日期的工具类 +import org.springframework.lang.Nullable; // 导入Spring框架中用于标记参数可空的注解 +import org.springframework.util.Assert; // 导入Spring框架中用于进行断言操作的工具类 + +import java.lang.reflect.Field; // 导入用于操作类字段反射的Field类 +import java.util.ArrayList; // 导入用于创建可变大小列表的ArrayList类 +import java.util.Arrays; // 导入用于操作数组的工具类 +import java.util.Date; // 导入用于处理日期的Date类 +import java.util.List; // 导入用于定义列表的List接口 + +// 定义一个名为ClazzDiff的类,用于比较两个对象的属性差异 +public class ClazzDiff { + // 定义一个方法,用于比较两个对象的属性,并返回包含差异信息的列表 + // obj1的属性值为空时,自动忽略与obj2对应属性的比较 + public List ClazzDiffColumn(Object obj1, Object obj2, @Nullable String... ignoreProperties) throws NoSuchFieldException, IllegalAccessException { + // 断言obj1不为空,如果为空则抛出异常并提示"obj1不是空的" + Assert.notNull(obj1, "obj1不是空的"); + // 断言obj2不为空,如果为空则抛出异常并提示"obj2不是空的" + Assert.notNull(obj2, "obj2不是空的"); + + // 创建一个ArrayList对象,用于存储属性差异信息 + List list = new ArrayList<>(); + + // 获取obj1对象的类类型 + Class obj1Class = obj1.getClass(); + // 获取obj2对象的类类型 + Class obj2Class = obj2.getClass(); + // 判断obj2是否是obj1Class的实例,如果不是则抛出异常并提示"传入的两个类不是同一个类" + if (!obj1Class.isInstance(obj2)) { + throw new IllegalArgumentException("传入的两个类不是同一个类"); + } + // 将可变参数ignoreProperties转换为List类型,如果ignoreProperties为null,则返回null + List ignoreList = (ignoreProperties != null? Arrays.asList(ignoreProperties) : null); + + // 获取obj1Class类中声明的所有字段 + Field[] obj1DeclaredFields = obj1Class.getDeclaredFields(); + // 遍历obj1的所有声明字段 + for (Field f : obj1DeclaredFields) { + // 设置当前字段可访问,打破Java的访问修饰符限制 + f.setAccessible(true); + // 获取obj1Class类中指定名称的字段 + Field obj1Field = obj1Class.getDeclaredField(f.getName()); + // 获取obj2Class类中指定名称的字段 + Field obj2Field = obj2Class.getDeclaredField(f.getName()); + // 设置obj1Field字段可访问 + obj1Field.setAccessible(true); + // 设置obj2Field字段可访问 + obj2Field.setAccessible(true); + + // 判断obj1Field的值不为空,并且该字段不在忽略列表中 + if (obj1Field.get(obj1) != null && (ignoreList == null ||!ignoreList.contains(obj1Field.getName()))) { + // 获取obj1Field字段上的ColumnInfo注解 + ColumnInfo columnInfo = obj1Field.getAnnotation(ColumnInfo.class); + // 获取obj1Field字段的值 + Object o1 = obj1Field.get(obj1); + // 获取obj2Field字段的值 + Object o2 = obj2Field.get(obj2); + + // 判断o1和o2转换为字符串后的值是否不相等 + if (!String.valueOf(o1).equals(String.valueOf(o2))) { + // 如果字段名包含"File" + if (f.getName().contains("File")) { + // 添加包含文件下载链接的差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : 文件下载,原先 : 文件下载"); + // 如果字段名包含"Video" + } else if (f.getName().contains("Video")) { + // 添加包含视频播放链接的差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : ,原先 : "); + // 如果字段名包含"Photo" + } else if (f.getName().contains("Photo")) { + // 添加包含图片展示链接的差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : ,原先 : "); + // 如果字段名包含"Time" + } else if (f.getName().contains("Time")) { + // 格式化日期并添加差异信息到列表中,若值为空则显示"空" + list.add(columnInfo.comment() + "-->现在 : [" + (o1 != null? DateUtils.format((Date) o1, "yyyy - MM - dd") : "空") + "],原先 : [" + (o2 != null? DateUtils.format((Date) o2, "yyyy - MM - dd") : "空") + "]"); + // 其他情况 + } else { + // 添加普通的属性差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : [" + o1 + "],原先 : [" + o2 + "]"); + } + } + } + } + + // 获取obj1Class父类中声明的所有字段 + Field[] obj1DeclaredFields2 = obj1Class.getSuperclass().getDeclaredFields(); + // 遍历obj1父类的所有声明字段 + for (Field f : obj1DeclaredFields2) { + // 设置当前字段可访问 + f.setAccessible(true); + // 获取obj1Class父类中指定名称的字段 + Field obj1Field = obj1Class.getSuperclass().getDeclaredField(f.getName()); + // 获取obj2Class父类中指定名称的字段 + Field obj2Field = obj2Class.getSuperclass().getDeclaredField(f.getName()); + // 设置obj1Field字段可访问 + obj1Field.setAccessible(true); + // 设置obj2Field字段可访问 + obj2Field.setAccessible(true); + + // 判断obj1Field的值不为空,并且该字段不在忽略列表中 + if (obj1Field.get(obj1) != null && (ignoreList == null ||!ignoreList.contains(obj1Field.getName()))) { + // 获取obj1Field字段上的ColumnInfo注解 + ColumnInfo columnInfo = obj1Field.getAnnotation(ColumnInfo.class); + // 获取obj1Field字段的值 + Object o1 = obj1Field.get(obj1); + // 获取obj2Field字段的值 + Object o2 = obj2Field.get(obj2); + + // 判断o1和o2转换为字符串后的值是否不相等 + if (!String.valueOf(o1).equals(String.valueOf(o2))) { + // 如果字段名包含"File" + if (f.getName().contains("File")) { + // 添加包含文件下载链接的差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : 文件下载,原先 : 文件下载"); + // 如果字段名包含"Video" + } else if (f.getName().contains("Video")) { + // 添加包含视频播放链接的差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : ,原先 : "); + // 如果字段名包含"Photo" + } else if (f.getName().contains("Photo")) { + // 添加包含图片展示链接的差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : ,原先 : "); + // 如果字段名包含"Time" + } else if (f.getName().contains("Time")) { + // 格式化日期并添加差异信息到列表中,若值为空则显示"空" + list.add(columnInfo.comment() + "-->现在 : [" + (o1 != null? DateUtils.format((Date) o1, "yyyy - MM - dd") : "空") + "],原先 : [" + (o2 != null? DateUtils.format((Date) o2, "yyyy - MM - dd") : "空") + "]"); + // 其他情况 + } else { + // 添加普通的属性差异信息到列表中 + list.add(columnInfo.comment() + "-->现在 : [" + o1 + "],原先 : [" + o2 + "]"); + } + } + } + } + // 返回包含属性差异信息的列表 + return list; + } + + // 定义一个方法,用于判断指定类中是否包含指定名称的字段 + public boolean hasField(Class c, String fieldName) { + // 获取指定类中声明的所有字段 + Field[] fields = c.getDeclaredFields(); + // 遍历所有字段 + for (Field f : fields) { + // 判断当前字段名是否与指定的字段名相等 + if (fieldName.equals(f.getName())) { + // 如果相等则返回true + return true; + } + } + // 遍历完所有字段后,若未找到匹配的字段,则返回false + return false; + } + + // 定义主方法,用于测试代码逻辑 + public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { + // 以下是测试代码,被注释掉,可根据需要启用 + // ChengpinEntity chengpinEntity1 = new ChengpinEntity(); + // chengpinEntity1.setId(2); + // chengpinEntity1.setXiaoshourenyuanId(3); + // chengpinEntity1.setChengpinUuidNumber("4"); + // chengpinEntity1.setChengpinName("6"); + // chengpinEntity1.setChengpinSchool("7"); + // chengpinEntity1.setChengpinLianxifangshi("8"); + // chengpinEntity1.setChengpinXiaoshouJine(9.0); + // chengpinEntity1.setChengpinTichengJine(10.0); + // chengpinEntity1.setLunwenTypes(11); + // chengpinEntity1.setLunwenXiaoshouJine(12.1); + // chengpinEntity1.setLunwenTichengJine(13.1); + // chengpinEntity1.setChengpinZhuangtaiTypes(14); + // chengpinEntity1.setChengpinFile("15"); + // chengpinEntity1.setChengpinText("16"); + // chengpinEntity1.setChengpinDelete(1); + // chengpinEntity1.setInsertTime(new Date()); + // chengpinEntity1.setUpdateTime(null); + // chengpinEntity1.setCreateTime(null); + + // ChengpinEntity chengpinEntity2 = new ChengpinEntity(); + // chengpinEntity2.setId(3); + // chengpinEntity2.setXiaoshourenyuanId(4); + // chengpinEntity2.setChengpinUuidNumber("4"); + // chengpinEntity2.setChengpinName("6"); + // chengpinEntity2.setChengpinSchool("7"); + // chengpinEntity2.setChengpinLianxifangshi("8"); + // chengpinEntity2.setChengpinXiaoshouJine(9.0); + // chengpinEntity2.setChengpinTichengJine(10.0); + // chengpinEntity2.setLunwenTypes(11); + // chengpinEntity2.setLunwenXiaoshouJine(12.1); + // chengpinEntity2.setLunwenTichengJine(13.1); + // chengpinEntity2.setChengpinZhuangtaiTypes(14); + // chengpinEntity2.setChengpinFile("16"); + // chengpinEntity2.setChengpinText("16"); + // chengpinEntity2.setChengpinDelete(1); + // chengpinEntity2.setInsertTime(null); + // chengpinEntity2.setUpdateTime(new Date()); + // chengpinEntity2.setCreateTime(null); + + // List strings = new ClazzDiff().ClazzDiffColumn(chengpinEntity1, chengpinEntity2,new String[]{"serialVersionUID"}); + // List strings = new ClazzDiff().ClazzDiffColumn(chengpinEntity1, chengpinEntity2); + // System.out.println(strings); + } +} \ No newline at end of file