package com.nuzar.fcms.std.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 字段标记注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Compare {
/**
* 字段名称
*/
String value();
}
package com.nuzar.fcms.std.util;
public class CompareNode {
/**
* 字段
*/
private String fieldKey;
/**
* 字段值
*/
private Object fieldValue;
/**
* 字段名称
*/
private String fieldName;
public String getFieldKey() {
return fieldKey;
}
public void setFieldKey(String fieldKey) {
this.fieldKey = fieldKey;
}
public Object getFieldValue() {
return fieldValue;
}
public void setFieldValue(Object fieldValue) {
this.fieldValue = fieldValue;
}
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
}
package com.nuzar.fcms.std.util;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
/**
* 使用须知: <br>
* (1)该工具类主要用于两个同类对象的属性值比较; <br>
* (2)使用本工具类前,请将对应的类属性上打上 @Compare("xxx") 注解,其中xxx为字段的表达名称;<br>
* (3)为了比较灵活,只有打了该注解才会进行比较,不打的字段则不会进行比较 <br>
* (4)比较后,只会返回有变化的字段,无变化的字符则不返回 <br>
*/
public class CompareUtils<T> {
private static final String COMMA = ",";
/**
* 属性比较
*
* @param source 源数据对象
* @param target 目标数据对象
* @return 对应属性值的比较变化
*/
public LinkedList<Map> compare(T source, T target) {
return compare(source, target, null);
}
/**
* 属性比较
*
* @param source 源数据对象
* @param target 目标数据对象
* @param ignoreCompareFields 忽略比较的字段
* @return 对应属性值的比较变化
*/
public LinkedList<Map> compare(T source, T target, List<String> ignoreCompareFields) {
if (Objects.isNull(source) && Objects.isNull(target)) {
return null;
}
Map<String, CompareNode> sourceMap = this.getFiledValueMap(source);
Map<String, CompareNode> targetMap = this.getFiledValueMap(target);
if (sourceMap.isEmpty() && targetMap.isEmpty()) {
return null;
}
// 如果源数据为空,则显示属性变化情况
LinkedList maps = doCompare(sourceMap, targetMap, ignoreCompareFields);
return maps;
}
private LinkedList<Map> doCompare(Map<String, CompareNode> sourceMap, Map<String, CompareNode> targetMap, List<String> ignoreCompareFields) {
LinkedList<Map> mapList = new LinkedList<Map>();
Set<String> keys = sourceMap.keySet();
for (String key : keys) {
CompareNode sn = sourceMap.get(key);
CompareNode tn = targetMap.get(key);
if (Objects.nonNull(ignoreCompareFields) && ignoreCompareFields.contains(sn.getFieldKey())) {
continue;
}
String sv = Optional.ofNullable(sn.getFieldValue()).orElse("").toString();
String tv = Optional.ofNullable(tn.getFieldValue()).orElse("").toString();
//司龄特殊处理,存在 0.0 != 0 的情况
if (sn.getFieldName().equals("司龄")){
BigDecimal snFieldValue = (BigDecimal) sn.getFieldValue();
BigDecimal tnFieldValue = (BigDecimal) tn.getFieldValue();
int i = snFieldValue.compareTo(tnFieldValue);
//值相等
if (i == 0){
continue;
}
}
// 只有两者属性值不一致时, 才显示变化情况
if (!sv.equals(tv)) {
Map map = new HashMap();
map.put("attr",sn.getFieldName());
map.put("oldAttr",sv);
map.put("newAttr",tv);
mapList.add(map);
}
}
return mapList;
}
private Map<String, CompareNode> getFiledValueMap(T t) {
if (Objects.isNull(t)) {
return Collections.emptyMap();
}
Field[] fields = t.getClass().getDeclaredFields();
if (Objects.isNull(fields) || fields.length == 0) {
return Collections.emptyMap();
}
Map<String, CompareNode> map = new LinkedHashMap();
for (Field field : fields) {
Compare compareAnnotation = field.getAnnotation(Compare.class);
if (Objects.isNull(compareAnnotation)) {
continue;
}
field.setAccessible(true);
try {
String fieldKey = field.getName();
CompareNode node = new CompareNode();
node.setFieldKey(fieldKey);
node.setFieldValue(field.get(t));
node.setFieldName(compareAnnotation.value());
map.put(field.getName(), node);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}