一、需求
系统中有用户、客户等信息时,需要记录修改前后的差异;
举例,用户信息修改了两次,第一次修改了微信、qq;第二次修改了qq:
{ "code":0, "data":[ { "systemUserId":1, "systemUserName":"超级管理员", "date":"2022-09-22 09:53:25", "detail":[ { "attribute":"weixinOne", "name":"微信", "valueOld":"5696", "valueNew":"56898" }, { "attribute":"qq", "name":"QQ", "valueOld":"131312268", "valueNew":"13131245" } ] }, { "systemUserId":1, "systemUserName":"超级管理员", "date":"2022-09-22 09:53:02", "detail":[ { "attribute":"qq", "name":"QQ", "valueOld":"131312267", "valueNew":"131312268" } ] } ], "msg":"" }
二、实现思路
1、对需要监控对象的字段使用注解,注解写明字段的名称;
2、使用反射比较两个对象,如果对象字段有注解,比较属性的值,如果值不一样,记录;
三、代码实现
1、定义注解
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * 自定义注解 * @author Administrator * */ @Retention(RetentionPolicy.RUNTIME) public @interface LogCompar { String value(); }
2、编写工具类
import cn.hutool.core.date.DateUtil; import xxxxx.LogCompar; import lombok.extern.java.Log; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; @Log public class ObjectCopareUtils { public static <T> List<EditLog> compareObject(Object oldBean, Object newBean) { List<EditLog> res = new ArrayList<>(16); String str = ""; T pojo1 = (T) oldBean; T pojo2 = (T) newBean; try { Class clazz = pojo1.getClass(); Field[] fields = pojo1.getClass().getDeclaredFields(); int i = 1; for (Field field : fields) { PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz); Method getMethod = pd.getReadMethod(); Object o1 = getMethod.invoke(pojo1); Object o2 = getMethod.invoke(pojo2); if (o1 == null || o2 == null) { continue; } if (!o1.toString().equals(o2.toString())) { LogCompar logCompar = field.getAnnotation(LogCompar.class); //判断是否有注解 if (logCompar != null) { EditLog tem = new EditLog(); //获取注解名称 tem.setAttribute(field.getName()); tem.setName(logCompar.value()); String typeName = o1.getClass().getName(); if (o2 != null) { if ("java.lang.String".equals(typeName) || "java.lang.Long".equals(typeName) || "java.lang.Integer".equals(typeName) || "java.lang.Float".equals(typeName) || "java.lang.Double".equals(typeName)) { tem.setValueOld(String.valueOf(o1)); tem.setValueNew(String.valueOf(o2)); } else if ("java.lang.Boolean".equals(typeName)) { tem.setValueOld((Boolean) o1 == true ? "true" : "false"); tem.setValueNew((Boolean) o2 == true ? "true" : "false"); } else if ("java.util.Date".equals(typeName) || "cn.hutool.core.date.DateTime".equals(typeName)) { String oldDay = DateUtil.format(((Date) o1), "yyyy-MM-dd HH:mm:ss"); String newDay = DateUtil.format(((Date) o2), "yyyy-MM-dd HH:mm:ss"); if(Objects.equals(oldDay,newDay)){ continue; } tem.setValueOld(oldDay); tem.setValueNew(newDay); } else { tem.setValueOld("类型匹配有误"); tem.setValueNew("类型匹配有误"); } } res.add(tem); } } } } catch (Exception e) { e.printStackTrace(); } return res; } }
3、其他代码
import lombok.Data; @Data public class EditLog { /*对象属性*/ private String attribute; /*对象注解名称*/ private String name; /*对象修改前值*/ private String valueOld; /*对象修改后值*/ private String valueNew; }
import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor public class StudentDO { /** * 学员ID */ private Long id; /** * 姓名 */ @LogCompar("名字") private String name; /** * 性别 */ @LogCompar("性别") private Integer sex; /** * 民族 */ @LogCompar("民族") private Integer nation; /** * 上课手机 */ @LogCompar("手机号码") private String classPhone; /** * 电话1 */ @LogCompar("备用手机") private String phoneOne; /** * 电话2 */ private String phoneTwo; /** * 微信 */ @LogCompar("微信") private String weixinOne; /** * */ private String weixinTwo; /** * QQ */ @LogCompar("QQ") private String qq; }
四、使用
//比较两个对象 List<EditLog> editLogs = ObjectCopareUtils.compareObject(dbStudent, updateObj);
业务细节,将本次日志追加到之前的修改中,查询的时候或者追加的时候对修改记录进行时间倒序排列(根据业务需要)。
//比较两个对象 List<EditLog> editLogs = ObjectCopareUtils.compareObject(dbStudent, updateObj); if (!CollUtil.isEmpty(editLogs)) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); List<ObjectValueCopare> updateEditLog = new ArrayList<>(); List<ObjectValueCopare> dbEditLog = dbStudent.getEditLog(); if (!CollUtil.isEmpty(dbEditLog)) { updateEditLog.addAll(dbEditLog); } ObjectValueCopare addEditLog = new ObjectValueCopare(); addEditLog.setSystemUserId(loginUserId); AdminUserDO adminUserDO = adminUserMapper.selectById(loginUserId); addEditLog.setSystemUserName(adminUserDO.getNickname()); addEditLog.setDate(DateUtil.formatDateTime(new Date())); addEditLog.setDetail(editLogs); updateEditLog.add(addEditLog); StudentDO updateEditLogStu = new StudentDO(); updateEditLogStu.setId(id); updateEditLogStu.setEditLog(updateEditLog); studentMapper.updateById(updateEditLogStu); }
记录数据样例
{ "code":0, "data":[ { "systemUserId":1, "systemUserName":"超级管理员", "date":"2022-09-22 09:53:25", "detail":[ { "attribute":"weixinOne", "name":"微信", "valueOld":"5696", "valueNew":"56898" }, { "attribute":"qq", "name":"QQ", "valueOld":"131312268", "valueNew":"13131245" } ] }, { "systemUserId":1, "systemUserName":"超级管理员", "date":"2022-09-22 09:53:02", "detail":[ { "attribute":"qq", "name":"QQ", "valueOld":"131312267", "valueNew":"131312268" } ] } ], "msg":"" }