最近公司的一个项目中有个需求,大致需求是这样的,需要把原来的表单修改,然后记录修改了哪些参数,因为是业务系统,表单有几十种,所以写个工具类来处理一下。
因为要比较两个表单对象,所以需要通过反射获取类的属性的getter方法,然后调用方法获取值并比较是否相同,返回不同的属性信息。
话不多说,直接上代码:
- 定义一个类接收比较后的返回值信息
@Data
public class PropertyModelInfo {
//属性名
private String propertyName;
// 属性值
private Object value;
//属性中文含义
private String propertyCn;
// 返回值类型
private Class> returnType;
}
- 定义一个类接收修改后的属性信息
@Data
public class ModifiedPropertyInfo implements Serializable {
// 对应的属性名
private String propertyName;
// 未修改之前的值
private Object oldValue;
// 修改后的值
private Object newValue;
//属性中文含义
private String propertyCn;
}
- 比较逻辑代码
public static List 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 oldObjectPropertyValue = getObjectPropertyValue(oldObj, ignoreProperties);
if (!CollectionUtils.isEmpty(oldObjectPropertyValue)) {
List modifiedPropertyInfos = new ArrayList<>(oldObjectPropertyValue.size());
List newObjectPropertyValue = getObjectPropertyValue(newObj, ignoreProperties);
Map 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 propertyCn = propertyModelInfo.getPropertyCn();
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 instanceof ArrayList> && newValue instanceof ArrayList> ){
// for (PetitionUserInfo v : (List) value){
// for (PetitionUserInfo o : (List) newValue) {
// if(v.getAcObjectId().equals(o.getAcObjectId())){
// List differentProperty = getDifferentProperty(v, o);
// modifiedPropertyInfos.addAll(differentProperty);
// }
// }
//
// }
// }
else if (!value.equals(newValue)) {
equal = true;
}
if (equal) {
modifiedPropertyInfo.setPropertyName(propertyName);
modifiedPropertyInfo.setPropertyCn(propertyCn);
modifiedPropertyInfo.setOldValue(value);
modifiedPropertyInfo.setNewValue(newValue);
modifiedPropertyInfos.add(modifiedPropertyInfo);
}
}else if (value != null || newValue != null){
modifiedPropertyInfo.setPropertyName(propertyName);
modifiedPropertyInfo.setPropertyCn(propertyCn);
modifiedPropertyInfo.setOldValue(value);
modifiedPropertyInfo.setNewValue(newValue);
modifiedPropertyInfos.add(modifiedPropertyInfo);
}
}
}
return modifiedPropertyInfos;
}
}
return Collections.emptyList();
}
public static List getObjectPropertyValue(T obj , String... ignoreProperties){
if (obj != null) {
Class> objClass = obj.getClass();
PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(objClass);
List modelInfos = new ArrayList<>(propertyDescriptors.length);
List ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
Map fieldMap = Arrays.stream(objClass.getDeclaredFields()).collect(Collectors.toMap(Field::getName, Function.identity()));
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);
if(fieldMap.containsKey(name)){
Field field = fieldMap.get(name);
if(field.isAnnotationPresent(FieldI18n.class)){
FieldI18n fieldI18n = field.getAnnotation(FieldI18n.class);
String newFieldName = fieldI18n.value();
propertyModelInfo.setPropertyCn(newFieldName);
}
}
propertyModelInfo.setValue(invoke);
propertyModelInfo.setReturnType(returnType);
modelInfos.add(propertyModelInfo);
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("反射获取类【"+objClass.getName()+"】方法异常," , e);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return modelInfos;
}
return Collections.emptyList();
}
注释的代码是表单对象里包括子对象集合,子对象的属性也要比较,根据自己需求来
以上内容参考: https://www.cnblogs.com/coderArron/p/16207944.html
- 测试:创建两个表单对象
@Data
static
class Petition {
@FieldI18n(value = "记录名称")
String caseName;
@FieldI18n(value = "编号")
String no;
@FieldI18n(value = "对象集合")
List petitionUserInfoList;
}
@Data
static
class PetitionUserInfo {
@FieldI18n(value = "对象id")
String acObjectId;
@FieldI18n(value = "对象姓名")
String userName;
@FieldI18n(value = "号码")
String number;
}
- 这里因为需要记录表单修改字段的中文含义,所以自定义了个注解来解析:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FieldI18n {
String value() default "";
}
- 测试代码:
public static void main(String[] args) {
Petition p = new Petition();
p.setCaseName("1111");
p.setNo("3");
List petitionUserInfoList = new ArrayList<>();
for (int i = 0; i < 2; i++) {
PetitionUserInfo petitionUserInfo = new PetitionUserInfo();
petitionUserInfo.setAcObjectId("uuii"+i);
petitionUserInfo.setUserName("张三"+i);
petitionUserInfo.setNumber("1311111111"+i);
petitionUserInfoList.add(petitionUserInfo);
}
p.setPetitionUserInfoList(petitionUserInfoList);
Petition p2 = new Petition();
p2.setCaseName("2222");
p2.setNo("4");
List petitionUserInfoList2 = new ArrayList<>();
for (int i = 0; i < 2; i++) {
PetitionUserInfo petitionUserInfo = new PetitionUserInfo();
petitionUserInfo.setAcObjectId("uuii"+i);
petitionUserInfo.setUserName("张三"+i);
petitionUserInfo.setNumber("1311111110"+i);
petitionUserInfoList2.add(petitionUserInfo);
}
p2.setPetitionUserInfoList(petitionUserInfoList2);
//改变值
List modifiedPropertyInfos = getDifferentProperty(p, p2);
System.out.println(JSONObject.toJSONString(modifiedPropertyInfos));
// for (ModifiedPropertyInfo modifiedPropertyInfo : modifiedPropertyInfos) {
// if (modifiedPropertyInfo.getPropertyName().equals("petitionUserInfoList")) {
// p.getPetitionUserInfoList().sort(Comparator.comparing(PetitionUserInfo::getAcObjectId));
// p2.getPetitionUserInfoList().sort(Comparator.comparing(PetitionUserInfo::getAcObjectId));
// for (int i = 0; i < p.getPetitionUserInfoList().size(); i++) {
// List differentProperty = getDifferentProperty(p.getPetitionUserInfoList().get(i), p2.getPetitionUserInfoList().get(i));
// System.out.println(JSONObject.toJSONString(differentProperty));
// }
// }
// }
}
结果:
[{"newValue":"2222","oldValue":"1111","propertyCn":"记录名称","propertyName":"caseName"},{"newValue":"4","oldValue":"3","propertyCn":"编号","propertyName":"no"},{"newValue":[{"acObjectId":"uuii0","number":"13111111100","userName":"张三0"},{"acObjectId":"uuii1","number":"13111111101","userName":"张三1"}],"oldValue":[{"acObjectId":"uuii0","number":"13111111110","userName":"张三0"},{"acObjectId":"uuii1","number":"13111111111","userName":"张三1"}],"propertyCn":"对象集合","propertyName":"petitionUserInfoList"}]
注释部分是判断表单的子对象集合是否有不同,如果有就去比较子对象集合。
到这工具类就算完成啦。



