利用反射实现——记录用户修改的字段及内容

需求:用户修改某一实体后,系统记录下用户修改了哪些内容
原方法:采取笨方法,取数据库中的老数据与新数据进行一一遍历比较

缺点:费时,代码量也较大

现方法:利用自定义注解以及反射相结合的方法,自动获取实体的属性以及注释,并比较新旧数据,返回修改内容

优点:缩减了代码量,尤其是属性很多的实体

自定义注解类

/**
 * 实体bean类字段描述 自定义注解
 * @author liu huangming
 * @date 2020-03-03 15:20:03
 */
@Documented  
@Inherited  
@Retention(RetentionPolicy.RUNTIME)  
@Target({ElementType.TYPE, ElementType.FIELD})// 次注解作用于类和字段上 
public @interface FieldAnnotation {
	String desc();
}

实体

/**  
 * 示例实体
 * @package: com.bean.smLayout
 * @author: liu huangming
 * @date: 2020年4月20日 下午5:31:34 
 */
public class UserInfo implements Serializable{
 
	private static final long serialVersionUID = 1L;
	
	private Integer id;
	@FieldAnnotation(desc = "用户名")
	private String userName;
	@FieldAnnotation(desc = "联系方式")
	private String phone;
	@FieldAnnotation(desc = "性别")
	private Integer sex;
	@FieldAnnotation(desc = "年龄")
	private Integer age;
	@FieldAnnotation(desc = "地址")
	private String address;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public Integer getSex() {
		return sex;
	}
	public void setSex(Integer sex) {
		this.sex = sex;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
}

解析方法

private static final String EDIT_TECHINFO_TEMPLATE = " 由 %s 修改为 %s";
 
/**
 * 获取用户修改内容
 * @author: liu huangming
 * @date: 2020年4月20日 下午5:41:08
 * @param oldData 数据库中的老数据实体
 * @param newData 新修改后的数据实体
 * @param changeMap 用于返回用户修改的属性以及对应修改的内容
 */
public void getChangeInfo(Object oldData,Object newData,Map<String, Object> changeMap) {
	try {
		// 获取该实体所有属性
		Field[] fields = oldData.getClass().getDeclaredFields();
		for (Field field : fields) {
			if(field.getName().equals("serialVersionUID") || field.getName().equals("id")) {
				continue;
			}
			// 根据属性名获取其get方法
			PropertyDescriptor pd = new PropertyDescriptor(field.getName(), oldData.getClass());
			Method method = pd.getReadMethod();
			// 调用get方法获取值,这里也可以直接使用field.get(oldData),field.get(newData)获取属性的值
			String preContent = method.invoke(oldData) != null ? method.invoke(preObject).toString() : "";
			String currContent = method.invoke(newData) != null ? method.invoke(object).toString() : "";
			// 记录下当前数据的ID
			if(!preContent.equals(currContent)){
				// 检索字段上是否有注解
				boolean fieldHasAnno = field.isAnnotationPresent(FieldAnnotation.class); 
				if(fieldHasAnno) {
					FieldAnnotation annotation = field.getAnnotation(FieldAnnotation.class);
					// 获取字段上的注解
					String descString = annotation.desc();
					changeMap.put(descString+":",String.format(EDIT_TECHINFO_TEMPLATE,method.invoke(oldData),method.invoke(newData) ));
				}
			}
		}
	} catch (IntrospectionException e) {
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		e.printStackTrace();
	} catch (IllegalArgumentException e) {
		e.printStackTrace();
	} catch (InvocationTargetException e) {
		e.printStackTrace();
	}
}
public String updateUserInfo(UserInfo userInfo) {
	Map<String, Object> changeMap = new HashMap<>();
	UserInfo oldData = userDao.getUserInfoById(userInfo.getId());
	getChangeInfo(oldData, userInfo, changeMap);
	for(Map.Entry<String, Object> entry : changeMap.entrySet()){
		System.out.println(entry.getKey());
		System.out.println(entry.getValue());
	}
	return SUCCESS;
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值