一: 代码的使用场景:
我使用的场景是当前台页面被修改了,需要获取被修改的字段进行日志保存
二: 以下的这个图有几点注意
- .getClass()是一个对象实例的方法,只有对象实例才有这个方法,具体的类是没有的。类的
Class类实例是通过.class获得的,显然,类没有.getClass()方法。
-
getFields()和getDeclaredFields()的区别
(1).getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
(2).getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。 -
PropertyDescriptor proDescriptor = new PropertyDescriptor(field.getName(), object.class);这行代码报错的问题我发现的有三点如下[主要问题就是get方法的规范性]
(1).有一个点需要注意序列化的问题,因为serialVersionUID(自己定义的名字) 没有get方法会造成
(2).Bean类的命名规范问题,
(3)get和set方法的命名规范问题必须是,get/set后的首字母必须大写
/**
第一个参数是你修改后的对象数据
第二个参数是需要传的具体想用的数据
第三个参数是未修改前的对象数据
*/
private void editLog(ChildBaseInfo childBaseInfo, String userName, ChildBaseInfo childBaseInfoById) {
try {
ChildBaseInfo childBaseInfo1 = new ChildBaseInfo();
Field[] fields = childBaseInfo1.getClass().getDeclaredFields();
for (Field field : fields) {
if (!"isSProblem".equals(field.getName())) {
// 获取Bean的某个属性的描述符
PropertyDescriptor proDescriptor = new PropertyDescriptor(field.getName(), ChildBaseInfo.class);
// 获得用于读取属性值的方法
Method methodGetUserName = proDescriptor.getReadMethod();
//这个地方是具体调用的的方法
childBaseInfo1 = (ChildBaseInfo) StringUtil.exange(childBaseInfo, childBaseInfoById, childBaseInfo1, field, methodGetUserName);
}
}
//下面的代码是自己的需求处理
childBaseInfo1.setId(childBaseInfoById.getId());
childBaseInfo1.setUpdateTime(childBaseInfo.getUpdateTime());
childBaseInfo1.setUpdateName(userName);
ChildBaseInfo childChange = mapper.editLogById(childBaseInfoById.getId());
if (StringUtil.isEmpty(childChange)) {
mapper.addChildBaseinfoChange(childBaseInfo1);
} else {
mapper.updateEditLogById(childBaseInfo1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
三: 下图代码时具体的实现
- 当然我这个是公共的方法参数上的使用用的都是Object
- * @param object2 过滤后封装的数据对象这个参数是不必须的.也可以用传进来的entity或者object1来封装都是可以的
- field.getGenericType().toString()这是获取当前属性的类型
- 使用if判断两个相同属性的属性值类来使用declaredFields.set(object2, s2);对过滤出来的数据进行重新封装
/**
* zhaofeng 修改数据的过滤
*
* @param entity 修改的数据对象
* @param object1 根据ID查询的原数据对象
* @param object2 过滤后封装的数据对象
* @param field
* @param methodGetUserName
* @return
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static Object exange(Object entity, Object object1, Object object2, Field field, Method methodGetUserName) throws IllegalAccessException, InvocationTargetException {
// 读取属性值
Object objUserName = methodGetUserName.invoke(object1);
Object objUserName1 = methodGetUserName.invoke(entity);
//获取根据ID查询的原数据对象的属性值
String s1 = objUserName == null ? "" : objUserName.toString();//避免空指针异常
//获取修改的数据对象
String s2 = objUserName1 == null ? "" : objUserName1.toString();//避免空指针异常
try {
Field declaredFields = null;
declaredFields = object2.getClass().getDeclaredField(field.getName());
declaredFields.setAccessible(true);
if (!"".equals(s2)) {
System.out.println("get userName:" + field.getName() + "值" + s1 + "=============>" + s2);
if (!s1.equals(s2)) {
if (field.getGenericType().toString().equals(
"class java.lang.Integer")) {
declaredFields.set(object2, Integer.valueOf(s2));
} else if (field.getGenericType().toString().equals(
"class java.util.Date")) {
String pattern = "EEE MMM dd HH:mm:ss zzz yyyy";
SimpleDateFormat df = new SimpleDateFormat(pattern, Locale.US);
Date date = df.parse(s2);
declaredFields.set(object2, date);
} else if (field.getGenericType().toString().equals(
"class java.math.BigDecimal")) {
declaredFields.set(object2, new BigDecimal(s2));
} else {
declaredFields.set(object2, s2);
}
}
} else {
if (field.getGenericType().toString().equals(
"class java.lang.Integer")) {
declaredFields.set(object2, 0);
} else if (field.getGenericType().toString().equals(
"class java.util.Date")) {
declaredFields.set(object2,"");
} else if (field.getGenericType().toString().equals(
"class java.math.BigDecimal")) {
declaredFields.set(object2, new BigDecimal(0));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return object2;
}
总结:
这个实际上就是使用反射来获取属性名和属性值的一个简单应用,通过获取属性名来进行比较值得是否相等