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); } }