JeeSite | 保存信息修改记录封装
前面写过两篇关于“保存信息修改记录”的内容,分别如下:
JeeSite | 保存信息修改记录续
回顾
第一篇文章通过类字段的比较返回一个有字段值不同的 List,然后自己构造表字段和字典的 Map 来生成修改前和修改后的差异字符串。从而实现“信息”修改“前”和修改“后”的对比记录。
第二篇文章不再自己构造表字段和字典的 Map,而是直接使用了 JeeSite 自带的 GenTable 类取代了自己构造表字段和字典的 Map,只是需要将“代码生成”中的“业务表配置”模块维护好就可以了。第二篇文章对第一篇文章进行了改进。
对于保存信息修改记录这个功能会在很多表单中进行使用,那么按照前面的解决方法,需要在每个表单对应的 Controller 中增加相同的代码来完成同样的事情,这样代码就重复了。因此,本篇就将这个功能封装为一个类,这样每次使用的时候只要实例化这个类,就可以完成“信息”修改“前”和修改“后”对比记录的功能了。
代码的具体功能前面都介绍过了,因此不进行太多的介绍了,只是介绍一下具体如何的封装。
差异字段列表生成
在 JeeSite 下的 src\main\java\com\thinkgem\jeesite\common\utils\ (该目录下存放了 JeeSite 项目的通用工具类,比如文件操作类、字符串操作类、日期操作类等)下新建一个CompareClassUtils.java 的类文件。
该文件的代码如下:
public class CompareClassUtils {
/**
* 获取两个对象同名属性内容不相同的列表
*
* @param class1
* 对象1
* @param class2
* 对象2
* @return
* @throws ClassNotFoundException
* @throws IllegalAccessException
*/
public static List<Map<String, Object>> compareTwoClass(Object class1, Object class2) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
// 获取对象的class
Class<?> clazz1 = class1.getClass();
Class<?> clazz2 = class2.getClass();
// 获取对象的属性列表
Field[] field1 = clazz1.getDeclaredFields();
Field[] field2 = clazz2.getDeclaredFields();
// 遍历属性列表field1
for (int i = 0; i < field1.length; i++) {
// 遍历属性列表field2
for (int j = 0; j < field2.length; j++) {
// 如果field1[i]属性名与field2[j]属性名内容相同
if (field1[i].getName().equals(field2[j].getName())) {
if (field1[i].getName().equals(field2[j].getName())) {
field1[i].setAccessible(true);
field2[j].setAccessible(true);
// 如果field1[i]属性值与field2[j]属性值内容不相同
try {
if (!compareTwo(field1[i].get(class1), field2[j].get(class2))) {
Map<String, Object> map2 = new HashMap<String, Object>();
map2.put("name", field1[i].getName());
map2.put("old", field1[i].get(class1));
map2.put("new", field2[j].get(class2));
list.add(map2);
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
}
return list;
}
/**
* 对比两个数据是否内容相同
*
* @param object1,object2
* @return boolean类型
*/
public boolean compareTwo(Object object1, Object object2) {
if (object1 == null && object2 == null) {
return true;
}
if (object1 == null && object2 != null) {
return false;
}
if (object1.equals(object2)) {
return true;
}
return false;
}
}
差异信息的拼接
差异信息的拼接需要使用数据表中字段的注释,如果代码中使用了字典则需要维护好对应的字典。在前面的文章中,在 GenTableService.java 增加了两个方法,并在 GenTableDao.xml 和 GenTableColumnDao.xml 增加了相应的 SQL。前面文章中,拼接差异信息定义在了表单对应的 Controller 中,即 catModifyInfo() 方法写在了各个表单的 Controller 中,而这里只需要将 catModifyInfo() 方法移动到 GenTableService.java 文件中即可。
在 GenTableService.java 下添加如下代码:
public String catModifyInfo(List<Map<String, Object>> list, String className) {
// 根据类名获得对应的表信息
GenTable genTable = getTableByClass(className.toString());
if ( genTable == null ) {
return "";
}
// 根据表id获取表相应的字段信息
List<GenTableColumn> columnList = getColumnByTable(genTable.getId());
if ( columnList == null ) {
return "";
}
Map<String, String> mapField = new HashMap<String, String>();
Map<String, String> mapDict = new HashMap<String, String>();
// 获得字段对应的Java属性和字段注释
for( GenTableColumn gtc : columnList ) {
mapField.put(gtc.getJavaField(), gtc.getComments());
}
// 获得字段对应的注释和对应的字典
for ( GenTableColumn gtc : columnList ) {
if ( StringUtils.isNotEmpty(gtc.getDictType())
&& StringUtils.isNotBlank(gtc.getDictType()) ) {
mapDict.put(gtc.getComments(), gtc.getDictType());
}
}
// 构造的修改字符串
String modInfo = "";
for ( Map<String, Object> mp : list) {
System.out.println(mp.get("name") + "---" + mp.get("old") + "---" + mp.get("new"));
System.out.println(mapField.get(mp.get("name")));
// 判断修改的值是否为字典
if ( mapDict.containsKey(mapField.get(mp.get("name"))) ) {
String oldValue = mp.get("old").toString();
String newValue = mp.get("new").toString();
String type = mapDict.get(mapField.get(mp.get("name")));
String oldStr = DictUtils.getDictLabel(oldValue, type, "");
String newStr = DictUtils.getDictLabel(newValue, type, "");
System.out.println(mapField.get(mp.get("name")) + ":(" + oldStr + ") => (" + newStr + ");");
modInfo += mapField.get(mp.get("name")) + ":(" + oldStr + ") => (" + newStr + ");";
} else {
modInfo += mapField.get(mp.get("name")) + ":(" + mp.get("old") + ") => (" + mp.get("new") + ");";
}
}
return modInfo;
}
上面的代码不再进行解释,前面已经有过具体的说明了。
封装后的调用
在 JeeSite 中,新建和修改的“保存”调用的都是 Controller 中的 "save" 方法,具体是修改还是新建,只要通过判断对象是否存在 id 即可,代码如下:
/*
* 如果id不为空,则表示为修改
*/
if ( StringUtils.isNotBlank(sellContract.getId()) ) {
SellContract sc = new SellContract();
// 获取原来的信息
sc = sellContractService.get(sellContract.getId()); // 比较修改后的信息和未修改的信息
List<Map<String, Object>> modList = CompareClassUtils.compareTwoClass(sc, sellContract);
// 生成差异信息
String strModifyInfo = genTableService.catModifyInfo(modList, "SellContract");
// 输出差异字符串
System.out.println(strModifyInfo); // 记录修改信息
ContractModifyInformation cmi = new ContractModifyInformation();
cmi.setContractId(sellContract.getId());
cmi.setModifyContent(strModifyInfo);
cmi.setModifyDept(UserUtils.getUser().getOffice().getId());
cmi.setModifyUser(UserUtils.getUser().getId());
cmi.setModifyDate(new Date());
contractModifyInformationService.save(cmi);
}
到此,具体的封装就完成了。
我的微信公众号:“码农UP2U”

JeeSite | 保存信息修改记录封装的更多相关文章
- JeeSite | 保存信息修改记录
需求点 在很多场景中信息是不能轻易被修改的,修改时要么需要具备权限,要么需要审批,但是无论是哪种方式,修改前后的数据都是需要留有“案底”的,也就是说关键的信息被修改后是有修改记录的,一般修改记录会记录 ...
- JeeSite | 保存信息修改记录续
遗留问题 上篇文章中遗留了一个问题,就是为了要关联类属性与注释,注释与字典的地方使用了两个map来逐个添加了相关的信息,如下所示: Map<String, String> mapField ...
- ASP.NET保存信息总结(Application、Session、Cookie、ViewState和Cache等) ZT
http://www.cnblogs.com/ranran/p/4065619.html http://www.cnblogs.com/jxlsomnus/p/4450911.html 以下是关于AS ...
- [ASP.net教程]ASP.NET保存信息总结(Application、Session、Cookie、ViewState和Cache等)
以下是关于ASP.NET中保存各种信息的对象的比较,理解这些对象的原理,对制作完善的程序来说是相当有必要的(摘至互联网,并非原创--xukunping)在ASP.NET中,有很多种保存信息的对象.例如 ...
- 玩转web之servlet(六)---session介绍及简单使用(登录验证中保存信息)
在浏览器与服务器进行交互时,往往需要把涉及到的一些数据保存下来,这时就需要使用cookie或session进行状态管理. 这篇文章先来说说session怎么用,首先在servlet中创建一个sessi ...
- WMI 获取硬件信息的封装函数与获取联想台式机的出厂编号方法
原文:WMI 获取硬件信息的封装函数与获取联想台式机的出厂编号方法 今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都是可以提取出来的,就自己把那些公共部分提出出来,以后如果要获取 某部分的 ...
- mybatis源码- 反射模块一(跟着MyBatis学反射):类级别信息的封装
目录 1 JavaBean 规范 2 Reflector和ReflectorFactory 2.1 Reflector 属性 2.1.1 属性 2.1.2 Invoker 接口 2.2 Reflect ...
- ASP.NET保存信息总结(Application、Session、Cookie、ViewState和Cache等)
以下是关于ASP.NET中保存各种信息的对象的比较,理解这些对象的原理,对制作完善的程序来说是相当有必要的(摘至互联网,并非原创--xukunping) 在ASP.NET中,有很多种保存信息的对象.例 ...
- C#实现在注册表中保存信息
C#实现在注册表中保存信息 最近做的项目需要在注册表中记录一些用户设置,方便在程序下次启动时读取设置,应用上次用户保存的设置,挺简单的. 写出来,方便记忆,以后要用,可以直接改改就能用. 1 usin ...
随机推荐
- poj 2631 Roads in the North (自由树的直径)
Roads in the North Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4513 Accepted: 215 ...
- 微信Pcweb登录简介
微信第三方PCweb扫码登录 准备工作 (1) 网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统. 在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之 ...
- 利用FOR XML PATH行转列(根据某字段分组,多行数据转成一行,并用逗号隔开)
CREATE TABLE #TEST(A VARCHAR(10) NULL,B VARCHAR(MAX) NULL) INSERT INTO #TESTSELECT 'A','A001'UNION A ...
- Mac上打开终端的7种简单方法
终端机是用于给Mac命令的便捷工具,尽管它可能会吓倒许多人.毕竟,这不像输入句子然后Mac响应那样简单.如果您有兴趣学习使用Terminal或只想输入一两个命令,我们在下面列出了一些文章,可以帮助您使 ...
- 基于STM32的无损压缩算法miniLZO移植,压缩率很高,20KB随机数压缩到638字节,耗时275us
说明: 1.miniLZO是采用C编写的无损压缩库. 2.提供了快速压缩和超快速解压缩能力. 3.比较耗内存,需要64KB内存用于压缩,对于H7这种大内存的,非常合适.或者有外置SRAM/SDRAM的 ...
- WPF之行为
Behavior的运用扩展了”交互“功能,以下记录示例: 在的项目中添加两个引用:Microsoft.Expression.Interactions.dllSystem.Windows.Interac ...
- 红黑树原理详解及golang实现
目录 红黑树原理详解及golang实现 二叉查找树 性质 红黑树 性质 operation 红黑树的插入 golang实现 类型定义 leftRotate RightRotate Item Inter ...
- How to: Initialize Business Objects with Default Property Values in XPO 如何:在 XPO 中用默认属性值初始化业务对象
When designing business classes, a common task is to ensure that a newly created business object is ...
- How to: Use the Entity Framework Code First in XAF 如何:在 XAF 中使用EF CodeFirst
This topic demonstrates how to create a simple XAF application with a business model in a DbContext ...
- Nexus-在项目中使用Maven私服,Deploy到私服、上传第三方jar包、在项目中使用私服jar包
场景 Ubuntu Server 上使用Docker Compose 部署Nexus(图文教程): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/ ...