|
|
@ -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<String> 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<String> 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<String> 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() + "-->现在 : <a type='success' style='text-decoration:none' class='el-button' href='" + o1 + "' >文件下载</a>,原先 : <a type='success' style='text-decoration:none' class='el-button' href='" + o2 + "' >文件下载</a>");
|
|
|
|
|
|
|
|
// 如果字段名包含"Video"
|
|
|
|
|
|
|
|
} else if (f.getName().contains("Video")) {
|
|
|
|
|
|
|
|
// 添加包含视频播放链接的差异信息到列表中
|
|
|
|
|
|
|
|
list.add(columnInfo.comment() + "-->现在 : <video src='" + o1 + "' width='100px' height='100px' controls='controls'></video>,原先 : <video src='" + o2 + "' width='100px' height='100px' controls='controls'></video>");
|
|
|
|
|
|
|
|
// 如果字段名包含"Photo"
|
|
|
|
|
|
|
|
} else if (f.getName().contains("Photo")) {
|
|
|
|
|
|
|
|
// 添加包含图片展示链接的差异信息到列表中
|
|
|
|
|
|
|
|
list.add(columnInfo.comment() + "-->现在 : <img src='" + o1 + "' width='100px' height='100px'>,原先 : <img src='" + o2 + "' width='100px' height='100px'>");
|
|
|
|
|
|
|
|
// 如果字段名包含"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() + "-->现在 : <a type='success' style='text-decoration:none' class='el-button' href='" + o1 + "' >文件下载</a>,原先 : <a type='success' style='text-decoration:none' class='el-button' href='" + o2 + "' >文件下载</a>");
|
|
|
|
|
|
|
|
// 如果字段名包含"Video"
|
|
|
|
|
|
|
|
} else if (f.getName().contains("Video")) {
|
|
|
|
|
|
|
|
// 添加包含视频播放链接的差异信息到列表中
|
|
|
|
|
|
|
|
list.add(columnInfo.comment() + "-->现在 : <video src='" + o1 + "' width='100px' height='100px' controls='controls'></video>,原先 : <video src='" + o2 + "' width='100px' height='100px' controls='controls'></video>");
|
|
|
|
|
|
|
|
// 如果字段名包含"Photo"
|
|
|
|
|
|
|
|
} else if (f.getName().contains("Photo")) {
|
|
|
|
|
|
|
|
// 添加包含图片展示链接的差异信息到列表中
|
|
|
|
|
|
|
|
list.add(columnInfo.comment() + "-->现在 : <img src='" + o1 + "' width='100px' height='100px'>,原先 : <img src='" + o2 + "' width='100px' height='100px'>");
|
|
|
|
|
|
|
|
// 如果字段名包含"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<String> strings = new ClazzDiff<ChengpinEntity>().ClazzDiffColumn(chengpinEntity1, chengpinEntity2,new String[]{"serialVersionUID"});
|
|
|
|
|
|
|
|
// List<String> strings = new ClazzDiff().ClazzDiffColumn(chengpinEntity1, chengpinEntity2);
|
|
|
|
|
|
|
|
// System.out.println(strings);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|