最近在做某个项目中,需要查找多个属性间不同的字段,但这些属性很多,一个一个的字段比较,很折腾,所以就自己写了一个快速的框架. 1.定义需要对比的结果,有新增,变更,删除,无变化四种结果
public enum CompareStatus {
/**
* 标记新数据
*/
NEW,
/**
* 标记变更数据
*/
CHANGE,
/**
* 标记删除数据
*/
DELETE,
/**
* 标记没有变更
*/
NO_CHANGE;
}
@AllArgsConstructor
@NoArgsConstructor
@Data
public class CompareResult {
/**
* 差异的结果属性
*/
private String propertyName;
/**
* 原来的属性
*/
private Object originalValue;
/**
* 当前的属性
*/
private Object currentValue;
}
@Data
@Slf4j
public class CompareObject<T> {
private CompareStatus status;
/**
* 之前原始的值
*/
private T original;
/**
* 当前的值
*/
private T current;
/**
* 需要对比的属性
*/
private List<String> includePropertys = new ArrayList<>();
/**
* 需要排除的属性
*/
private List<String> excludePropertys = new ArrayList<>();
/**
* 不相等的比较结果
*/
private List<CompareResult> noEqualCompareResults = new ArrayList<>();
/**
* 值相同比较结果
*/
private List<CompareResult> equalCompareResults = new ArrayList<>();
/**
* 计算比较结果
* @param cls 比较的类
*/
public void compareDiff(Class<T> cls) {
Assert.notNull(this.current, "不允许当前比较对象为空");
boolean isEqual = true;
//clazz.getDeclaredFields()不能获取父的属性
Field[] fields = this.getAllFields(cls);
for(Field field : fields) {
try {
//判断属性是否在包含的属性里面
if (CollectionUtils.isNotEmpty(this.includePropertys) && !this.includePropertys
.contains(field.getName())) {
continue;
}
//判断属性是否在排除的包含属性里面
if (CollectionUtils.isNotEmpty(this.excludePropertys) && this.excludePropertys
.contains(field.getName())) {
continue;
}
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), cls);
Method getMethod = pd.getReadMethod();
Object o1 = this.original == null ? null : getMethod.invoke(this.original);
Object o2 = this.current == null ? null : getMethod.invoke(this.current);
CompareResult compareResult = new CompareResult(field.getName(), o1, o2);
//判断是否有自定义注解
if (field.getDeclaredAnnotation(CompareSpi.class) != null) {
CompareSpi compareSpi = field.getDeclaredAnnotation(CompareSpi.class);
//自定义比较内容
CompareSpiService compareSpiService = (CompareSpiService) compareSpi.compareClass().newInstance();
if (compareSpiService.compareObject(o1, o2)) {
this.equalCompareResults.add(compareResult);
} else {
isEqual = false;
this.noEqualCompareResults.add(compareResult);
}
} else {
if (Objects.equals(o2, o1)) {
this.equalCompareResults.add(compareResult);
} else {
isEqual = false;
this.noEqualCompareResults.add(compareResult);
}
}
} catch (Exception e) {
log.debug(e.getMessage());
}
}
if (this.original == null) {
this.status = CompareStatus.NEW;
} else if (isEqual) {
this.status = CompareStatus.NO_CHANGE;
} else {
this.status = CompareStatus.CHANGE;
}
}
private Field[] getAllFields(Class clazz) {
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
}
BaseModel orgDepartmentDto = new BaseModel();
orgDepartmentDto.setCreateUserCode("1111");
BaseModel orgDepartmentDto2 = new BaseModel();
orgDepartmentDto2.setCreateUserCode("122211");
CompareObject<BaseModel> compareObject = new CompareObject<>();
compareObject.setCurrent(orgDepartmentDto);
compareObject.setOriginal(orgDepartmentDto2);
compareObject.compareDiff(BaseModel.class);
log.info(compareObject.getStatus().name());
log.info(compareObject.getEqualCompareResults().toString());
log.info(compareObject.getNoEqualCompareResults().toString());
自此,就能快速的获取两个对象的差异,面不需要一个一个的比较