一、记录跟变信息对象
/** * @author FengQing * @program yf-client * @description * @date 2023/11/01 */ @Getter @Setter @ToString public class ChangePropertyMsg { /** * 变更信息 */ private String changeMsg; /** * 变更属性集合 */ private List<String> properties; }
二、工具类(传入两个相同类型的对象,对比属性得到修改信息)
提示:监听属性变化是通过【ApiModelProperty】注解,当然你也可以通过自定义注解实现;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ArrayUtil; import com.yf.client.entity.log.ChangePropertyMsg; import com.yf.utils.StringUtils; import lombok.extern.slf4j.Slf4j; import io.swagger.annotations.ApiModelProperty; import org.apache.commons.lang.ObjectUtils; import java.lang.reflect.Field; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; /** * @author FengQing * @program yf-client * @description * @date 2023/11/01 */ @Slf4j public class BeanChangeUtil<T> { /** * 传入两个相同类型的对象,对比属性得到修改信息 * @param oldBean * @param newBean * @return 属性修改信息 */ public static <aClass> String getChangeInfo(Object oldBean, Object newBean){ Class aClass = oldBean.getClass(); BeanChangeUtil<aClass> t = new BeanChangeUtil<>(); ChangePropertyMsg cfs = t.contrastObj(oldBean, newBean); if (StringUtils.isNotEmpty(cfs.getChangeMsg())) { return cfs.getChangeMsg(); } return null; } /** * 传入两个相同类型的对象,对比属性得到修改信息 * @param oldBean * @param newBean * @return **完整属性修改信息** */ public ChangePropertyMsg contrastObj(Object oldBean, Object newBean) { // 转换为传入的泛型T T oldPojo = (T) oldBean; // 通过反射获取类型及字段属性 Field[] fields = oldPojo.getClass().getDeclaredFields(); return jdk8OrAfter(Arrays.asList(fields), oldPojo, (T) newBean); } // lambda表达式,表达式内部的变量都是final修饰,需要传入final类型的数组 private ChangePropertyMsg jdk8OrAfter(List<Field> fields, T oldBean, T newBean) { ChangePropertyMsg cf = new ChangePropertyMsg(); // 创建字符串拼接对象 StringBuilder str = new StringBuilder(); List<String> fieldList = new ArrayList<>(); fields.forEach(field -> { field.setAccessible(true); if (field.isAnnotationPresent(ApiModelProperty.class)) { try { // 获取属性值 Object newValue = field.get(newBean); Object oldValue = field.get(oldBean); if (StringUtils.isNotNull(newValue)) { if (ObjectUtils.notEqual(oldValue, newValue)) { boolean isOldValueArray = ArrayUtil.isArray(oldValue); boolean isNewValueArray = ArrayUtil.isArray(newValue); if (isOldValueArray && isNewValueArray) { Object[] oldArray = (Object[]) oldValue; Object[] newArray = (Object[]) newValue; if (!Arrays.deepEquals(oldArray, newArray)) { fieldList.add(field.getName()); str.append(field.getAnnotation(ApiModelProperty.class).value() + ":"); str.append("修改前=【" + Arrays.toString(oldArray) + "】,修改后=【" + Arrays.toString(newArray) + "】;\n"); } } else { fieldList.add(field.getName()); str.append(field.getAnnotation(ApiModelProperty.class).value() + ":"); str.append("修改前=【" + formatPropertyValue(oldValue) + "】,修改后=【" + formatPropertyValue(newValue) + "】;\n"); } } } } catch (Exception e) { log.error("比对Bean属性是否变化失败,", e); } } }); cf.setChangeMsg(str.toString()); cf.setProperties(fieldList); return cf; } /** * 时间处理 * @param value * @return */ private static Object formatPropertyValue(Object value) { if (value instanceof Date) { return DateUtil.format((Date) value, "yyyy-MM-dd"); } else if (value instanceof LocalDateTime) { LocalDateTime localDateTimeValue = (LocalDateTime) value; return localDateTimeValue.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } return value; } }
三、在修改业务中使用步骤(我这边使用的mybatis-plus,其它的同理方式处理)
/** * 更新操作(业务层) * @param channel * @return */ @Override @Transactional(rollbackFor = {Exception.class, RuntimeException.class, MybatisPlusException.class}) public void updateChannel(ChannelParam channel) { // 1、查询修改前的数据 ChannelVo channelVo = this.selectChannelById(channel.getId());
// 2、修改前的对象跟前端返回的对象不一样如:前端传来的“ChannelParam”,修改前是“ChannelVo”对象,把它复制到统一对象中 ChannelParam oldParam = new ChannelParam(); BeanUtil.copyProperties(channelVo, oldParam); Channel data = new Channel;
BeanUtil.copyProperties(channel, data); super.updateById(data); // 记录日志对象 ChannelLogParam logParam = new ChannelLogParam();
// 调用监听属性变化工具类 BeanChangeUtil<ChannelParam> t = new BeanChangeUtil<>(); ChangePropertyMsg cfs = t.contrastObj(oldParam, channel); if (StringUtils.isNotBlank(cfs.getChangeMsg())) {
logParam.setUpdateObj(cfs.getProperties().toString()); logParam.setUpdateMsg(cfs.getChangeMsg()); } // 添加日志记录 channelLogService.insertChannelLogging(logParam); }
四、数据库存储效果如下图:
到这里就大功告成了。
标签:return,记录,oldBean,Object,value,修改,Java,import From: https://www.cnblogs.com/springclout/p/17855236.html