说明:代码中的Sring… param 为可拓展字段,可以理解为String[] param
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
/**
* @description: 对比对象变化值的工具类
* @fileName: CompareObjectPropertyUtil.java
* @author: Sure
* @createAt: 2022/02/09 11:49
*/
@Slf4j
@Component
public class CompareDifferObjectInfo {
/**
* 注入字典查询接口
*/
@Resource
private DictCommonApi dictCommonApi;
private final static String NO = "0";
/**
* 比较两个对象不同的属性并记录返回
*
* @param oldObj 旧对象
* @param newObj 新对象
* @param ignoreProperties 可忽略比的属性
* @return 修改的内容
*/
public <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();
String propertyComment = propertyModelInfo.getPropertyComment();
Object value = propertyModelInfo.getValue();
if (objectMap.containsKey(propertyName)) {
Object newValue = objectMap.get(propertyName);
ModifiedPropertyInfo modifiedPropertyInfo = new ModifiedPropertyInfo();
if (value != null && newValue != null) {
if (!value.equals(newValue)) {
modifiedPropertyInfo.setPropertyName(propertyName);
modifiedPropertyInfo.setPropertyComment(propertyComment);
modifiedPropertyInfo.setOldValue(value);
modifiedPropertyInfo.setNewValue(newValue);
modifiedPropertyInfos.add(modifiedPropertyInfo);
}
} else if (isaBoolean(newValue == null, value != null, StringUtils.isBlank(value.toString()))
|| (isaBoolean(value == null, newValue != null, StringUtils.isBlank(newValue.toString())))) {
modifiedPropertyInfo.setPropertyName(propertyName);
modifiedPropertyInfo.setPropertyComment(propertyComment);
modifiedPropertyInfo.setOldValue(value);
modifiedPropertyInfo.setNewValue(newValue);
modifiedPropertyInfos.add(modifiedPropertyInfo);
}
}
}
return modifiedPropertyInfos;
}
}
return Collections.emptyList();
}
/**
* 通过反射获取对象的属性名称、getter返回值类型、属性值等信息
*
* @param obj 对象
* @param ignoreProperties 可忽略比对的属性
* @return 修改的内容
*/
public <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);
Field[] fields = objClass.getDeclaredFields();
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
for (Field field : fields) {
field.setAccessible(true);
String fieldName = field.getName();
if (ignoreList == null || !ignoreList.contains(fieldName)) {
PropertyModelInfo propertyModelInfo = new PropertyModelInfo();
propertyModelInfo.setPropertyName(fieldName);
propertyModelInfo.setReturnType(field.getType());
Object fieldValue = getFieldValueByName(fieldName, obj);
// 通过自定义注解拿到属性注释
if (field.isAnnotationPresent(PropertyName.class)) {
PropertyName annotation = field.getAnnotation(PropertyName.class);
propertyModelInfo.setPropertyComment(annotation.name());
// 如果是字典项,则将code转换成name
// Object finalFieldValue = fieldValue;
if (isaBoolean(!ObjectUtils.isEmpty(annotation.dictName()), !ObjectUtils.isEmpty(fieldValue), " ".equals(fieldValue))) {
if ("yesNo".equals(annotation.dictName())) {
fieldValue = NO.equals(fieldValue) ? "无" :"有";
}
if ("userrole".equals(annotation.dictName())) {
fieldValue = NO.equals(fieldValue) ? "角色" :"人";
}
// if (!ObjectUtils.isEmpty(annotation.idName()) && !ObjectUtils.isEmpty(annotation.valueName())) {
// List<Map<String, Object>> mapList = dictCommonApi.queryAll(annotation.dictName(), annotation.idName() + "," + annotation.valueName(), null, null);
// Map<Object, Object> objectMap = mapList.stream().collect(Collectors.toMap(p -> p.get(annotation.idName()).toString(), s -> s.get(annotation.valueName()),(a1,a2)->a2));
// if (ObjectUtils.isEmpty(objectMap.get(fieldValue.toString()))) {
// fieldValue = fieldValue;
// }else {
// fieldValue = objectMap.get(fieldValue.toString());
// }
// }
}
}
propertyModelInfo.setValue(fieldValue == null ? "" : fieldValue);
modelInfos.add(propertyModelInfo);
}
}
return modelInfos;
}
return Collections.emptyList();
}
private static Object getFieldValueByName(String fieldName, Object o) {
try {
String firstLetter = fieldName.substring(0, 1).toUpperCase();
String getter = "get" + firstLetter + fieldName.substring(1);
Method method = o.getClass().getMethod(getter, new Class[]{});
Object value = method.invoke(o, new Object[]{});
return value;
} catch (Exception e) {
log.error(e.getMessage(), e);
return null;
}
}
/**
* 判断三个值
*/
private boolean isaBoolean(boolean b, boolean b2, boolean blank) {
return b && b2 && !blank;
}
}