Java项目C中 有一处逻辑,对于资源数据(类型为ResourceItem,拥有int/double/boolean/String类型数十个字段),需要比对资源数据每次变更的差异,并描述出变更情况。并非所有的字段都需要比对,如id字段则不参与比对。
依次比对每一个字段编写代码比对,将是个重苦力活。高级语言给予了我们诸多便利,应当加以利用。
首先定义自己的注解,value值用作字段描述
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface RevisionColumn { String value(); }
为ResourceItem所有待比对字段添加该注解,如
public class ResourceItem { private int id; private int revision; private ResourceItemStatus status; @RevisionColumn("节点") private String node; @RevisionColumn("是否物理隔离") private boolean physicalIsolation; @RevisionColumn("整机:单盘上限(%)") private int machineDiskLimit; //... }
介绍比对逻辑前,首先定义记录对象字段差异的实体类型
public class FieldChangeInfo implements Serializable{ private String propertyName; private String propertyHeader; private Object from; private Object to; public FieldChangeInfo() { } public FieldChangeInfo(String propertyName, String propertyHeader, Object from, Object to) { this.propertyName = propertyName; this.propertyHeader = propertyHeader; this.from = from; this.to = to; } @Override public boolean equals(Object obj) { if (!(obj instanceof FieldChangeInfo)) return false; if (obj == this) return true; FieldChangeInfo rhs = (FieldChangeInfo) obj; return new EqualsBuilder(). append(propertyName, rhs.propertyName). append(propertyHeader, rhs.propertyHeader). append(from, rhs.from). append(to, rhs.to). isEquals(); } public String getPropertyName() { return propertyName; } public void setPropertyName(String propertyName) { this.propertyName = propertyName; } public String getPropertyHeader() { return propertyHeader; } public void setPropertyHeader(String propertyHeader) { this.propertyHeader = propertyHeader; } public Object getFrom() { return from; } public void setFrom(Object from) { this.from = from; } public Object getTo() { return to; } public void setTo(Object to) { this.to = to; } }
FieldChangeInfo
Resource数据比对逻辑,实现如下工具方法
1、参数接受ResourceItem新旧两个对象
2、通过反射,class.getDeclaredFields获取类型的所有字段
3、调用Field实例的getAnnotation方法,获取RevisionColumn注解对象,若不为null,则说明该字段设置了该注解,进行比对
4、获取字段值,检测空引用,调用equals方法做值比对,出现不匹配,则创建FiledChangeInfo对象记录差异信息
5、返回差异信息集合
public static List<FieldChangeInfo> getResourceItemFieldChangeInfo(ResourceItem originalItem, ResourceItem updatedItem) { try { List<FieldChangeInfo> fieldChangeInfos = new LinkedList<>(); for (Field field : ResourceItem.class.getDeclaredFields()) { RevisionColumn revisionColumn = field.getAnnotation(RevisionColumn.class); if (revisionColumn != null) { field.setAccessible(true); Object originalValue = field.get(originalItem); Object updatedValue = field.get(updatedItem); if (originalValue == null && updatedValue == null) continue; if (originalValue == null || !originalValue.equals(updatedValue)){ FieldChangeInfo fieldChangeInfo = new FieldChangeInfo(); fieldChangeInfo.setFrom(originalValue); fieldChangeInfo.setTo(updatedValue); fieldChangeInfo.setPropertyName(field.getName()); fieldChangeInfo.setPropertyHeader(revisionColumn.value()); fieldChangeInfos.add(fieldChangeInfo); } } } return fieldChangeInfos; } catch (IllegalAccessException e) { throw new RuntimeException("检测ResourceItem字段变更时出现异常"); } }
getResourceItemFieldChangeInfo
若有必要,则可以稍加重构转换为泛型方法,支持何种数据类型的差异性检测
时间: 2024-10-25 11:19:20