// User 对象实体类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="用户对象", description="用户表")
public class User {
@ApiModelProperty(value = "用户id")
private int id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "年龄")
private int age;
@ApiModelProperty(value = "地址")
private String address;
}
// User 修改日志类
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "userUpdateLog对象", description = "用户修改日志表")
public class UserUpdateLog {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
private Long userLogId;
@ApiModelProperty(value = "修改类型")
private String modifyField;
@ApiModelProperty(value = "修改前内容")
private String beforeModification;
@ApiModelProperty(value = "修改后内容")
private String afterModification;
}
// 正式代码测试类
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@RunWith(SpringRunner.class)
public class demo1 {
/**
* JDK内省类库:
* PropertyDescriptor类:(属性描述器)
* PropertyDescriptor类表示JavaBean类通过存储器导出一个属性。主要方法:
* 1. getPropertyType(),获得属性的Class对象;
* 2. getReadMethod(),获得用于读取属性值的方法;
* 3. getWriteMethod(),获得用于写入属性值的方法;
* 4. hashCode(),获取对象的哈希值;
* 5. setReadMethod(Method readMethod),设置用于读取属性值的方法;
* 6. setWriteMethod(Method writeMethod),设置用于写入属性值的方法
*/
@Test
public void test1(){
User beforeUser=new User();
beforeUser.setId(1);
beforeUser.setName("小明");
beforeUser.setAge(20);
beforeUser.setAddress("北京");
User afterUser=new User();
afterUser.setId(2);
afterUser.setName("小黑");
afterUser.setAge(30);
afterUser.setAddress("上海");
List<UserUpdateLog> userUpdateLogs = contrastObj(afterUser, beforeUser);
System.out.println(userUpdateLogs);
}
public static List<UserUpdateLog> contrastObj(Object afterObj, Object beforeObj) {
User afterUser = (User) afterObj;
User beforeUser = (User) beforeObj;
List<UserUpdateLog> updateLogList = Lists.newArrayList();
try {
Class clazz = afterUser.getClass();
Field[] fields = afterUser.getClass().getDeclaredFields();
for (Field field : fields) {
UserUpdateLog userUpdateLog = new UserUpdateLog();
if("serialVersionUID".equals(field.getName())){
continue;
}
//获取 clazz 类型中的 propertyName 的属性描述器
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
// 获得读取属性值的方法 getReadMethod()
Method getMethod = pd.getReadMethod();
Object o1 = getMethod.invoke(afterUser);
Object o2 = getMethod.invoke(beforeUser);
String s1 = o1 == null ? "" : o1.toString();//避免空指针异常
String s2 = o2 == null ? "" : o2.toString();//避免空指针异常
//思考下面注释的这一行:会bug的,虽然被try catch了,程序没报错,但是结果不是我们想要的
// todo 我的理解 o1 o2 是object 类型
//if (!o1.toString().equals(o2.toString())) {
if (!s1.equals(s2)) {
userUpdateLog.setModifyField(field.getAnnotation(ApiModelProperty.class).value());
userUpdateLog.setBeforeModification(s2);
userUpdateLog.setAfterModification(s1);
updateLogList.add(userUpdateLog);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return updateLogList;
}
// 控制台输出结果
[UserUpdateLog(userLogId=null, modifyField=用户id, beforeModification=1, afterModification=2), UserUpdateLog(userLogId=null, modifyField=姓名, beforeModification=小明, afterModification=小黑), UserUpdateLog(userLogId=null, modifyField=年龄, beforeModification=20, afterModification=30), UserUpdateLog(userLogId=null, modifyField=地址, beforeModification=北京, afterModification=上海)]
本文介绍了一种使用Java反射和内省API对比两个User对象实例差异的方法,并将差异记录到UserUpdateLog实体中。通过PropertyDescriptor获取对象属性的读取和写入方法,比较前后对象属性值的变化,生成修改日志。
300

被折叠的 条评论
为什么被折叠?



