最新项目中要加操作日志,同时要把用户修改了那些字段记录下来,在更新的时候就需要比较之前的数据和现在的数据有哪些不同,这么多类一个一个的比较就太麻烦了,所以打算写一个工具类。
主要思想还是通过反射获取类的属性的getter方法,调用getter方法获取值并比较是否相同,相同就忽略不同就返回属性信息,方法都不复杂,主要是利用反射思想。
代码如下:
定义一个类保存比较后的返回值信息
@Data public class PropertyModelInfo { //属性名 private String propertyName; // 属性值 private Object value; // 返回值类型 private Class<?> returnType; }
修改后的属性信息:
public class ModifiedPropertyInfo implements Serializable { // 对应的属性名 private String propertyName; // 未修改之前的值 private Object oldValue; // 修改后的值 private Object newValue; }
逻辑代码:
/** * 比较两个对象属性值是否相同 * 如果不同返回修改过的属性信息 * @param oldObj * @param newObj * @param ignoreProperties * @param <T> * @return 修改过的属性字段 */ public static <T> List<ModifiedPropertyInfo> getDifferentProperty(T oldObj , T newObj , String... ignoreProperties){ if (oldObj != null && newObj != null) { // 比较全部字段 if (ignoreProperties == null || ignoreProperties.length > 0) { if (oldObj.equals(newObj)) { return Collections.emptyList(); } } List<PropertyModelInfo> oldObjectPropertyValue = getObjectPropertyValue(oldObj, ignoreProperties); if (!CollectionUtils.isEmpty(oldObjectPropertyValue)) { List<ModifiedPropertyInfo> modifiedPropertyInfos = new ArrayList<>(oldObjectPropertyValue.size()); List<PropertyModelInfo> newObjectPropertyValue = getObjectPropertyValue(newObj, ignoreProperties); Map<String , Object> objectMap = new HashMap<>(newObjectPropertyValue.size()); // 获取新对象所有属性值 for (PropertyModelInfo propertyModelInfo : newObjectPropertyValue) { String propertyName = propertyModelInfo.getPropertyName(); Object value = propertyModelInfo.getValue(); objectMap.put(propertyName , value); } for (PropertyModelInfo propertyModelInfo : oldObjectPropertyValue) { String propertyName = propertyModelInfo.getPropertyName(); Object value = propertyModelInfo.getValue(); if (objectMap.containsKey(propertyName)) { Object newValue = objectMap.get(propertyName); ModifiedPropertyInfo modifiedPropertyInfo = new ModifiedPropertyInfo(); if (value != null && newValue != null) { // 是否相等 boolean equal = false; if (value instanceof BigDecimal) { // BigDecimal 用 equal 比较 if (((BigDecimal) value).compareTo((BigDecimal) newValue) != 0) { equal = true; } }else if (!value.equals(newValue)) { equal = true; } if (equal) { modifiedPropertyInfo.setProperty(propertyName); modifiedPropertyInfo.setOldValue(value); modifiedPropertyInfo.setNewValue(newValue); modifiedPropertyInfos.add(modifiedPropertyInfo); } }else if (value != null || newValue != null){ modifiedPropertyInfo.setProperty(propertyName); modifiedPropertyInfo.setOldValue(value); modifiedPropertyInfo.setNewValue(newValue); modifiedPropertyInfos.add(modifiedPropertyInfo); } } } return modifiedPropertyInfos; } } return Collections.emptyList(); } /** * 通过反射获取对象的属性名称、getter返回值类型、属性值等信息 * @param obj * @param ignoreProperties * @param <T> * @return */ public static <T> List<PropertyModelInfo> getObjectPropertyValue(T obj , String... ignoreProperties){ if (obj != null) { Class<?> objClass = obj.getClass(); PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(objClass); List<PropertyModelInfo> modelInfos = new ArrayList<>(propertyDescriptors.length); List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { Method readMethod = propertyDescriptor.getReadMethod(); String name = propertyDescriptor.getName(); if (readMethod != null && (ignoreList == null || !ignoreList.contains(name))) { Object invoke = null; Class<?> returnType = readMethod.getReturnType(); try { invoke = readMethod.invoke(obj); PropertyModelInfo propertyModelInfo = new PropertyModelInfo(); propertyModelInfo.setPropertyName(name); propertyModelInfo.setValue(invoke); propertyModelInfo.setReturnType(returnType); modelInfos.add(propertyModelInfo); } catch (IllegalAccessException | InvocationTargetException e) { LOGGER.error("反射获取类【"+objClass.getName()+"】方法异常," , e); } } } return modelInfos; } return Collections.emptyList(); }
测试:
HouseInfo houseInfo = new HouseInfo(); houseInfo.setAddress("test1"); HouseInfo houseInfo2 = new HouseInfo(); houseInfo2.setAddress("test2"); //改变值 List<ModifiedPropertyInfo> modifiedPropertyInfos = ReflectUtil.getDifferentProperty(houseInfo, houseInfo2); System.out.println(modifiedPropertyInfos); // 不改变值 houseInfo2.setAddress("test1"); modifiedPropertyInfos = ReflectUtil.getDifferentProperty(houseInfo, houseInfo2); System.out.println(modifiedPropertyInfos);
结果:
[ModifiedPropertyInfo(propertyName=address, oldValue=test1, newValue=test2)] []
步骤:
1、获取对象的属性属性值
2、跟另一个对象的所有属性值比较
能力一般,水平有限,如有错误,请多指出