基于数据集事件监听实现数据日志记录
监听数据表中数据的增删改查,并记录对应表详细操作内容,运行效果如下图所示
特别说明
- 由于使用后端 Java 数据集操作监听事件来记录操作日志,建议使用本地 ide 进行开发
- 作为演示案例,为防止日志产生过多,本例只监听 contact 数据集,在实际使用中按需设置事件 condition 中的 event.tableName 参数
添加数据集
在 ide 中,添加“操作日志”数据集,包含表名、操作类型、操作内容、操作时间及操作人等列,存储用户操作记录。
添加事件处理类
在 main.common 下新增事件处理类 EventHandler.java
- 引用操作日志 mapper 类
- 新增表查询方法、获取用户方法及插入日志方法
public JSONObject getColumnInfo(String dataModal) {
// 获取服务名
String serviceName = ContextUtil.getServiceName();
//查询表信息
JSONObject tableInfo = ServiceUtil.get(serviceName, "/main/dbrest/modelinfo/" + dataModal);// 返回JSONArray类型
JSONArray columns = tableInfo.getJSONArray("fields");
JSONObject columnsObj = new JSONObject();
columns.forEach(item -> {
JSONObject column = (JSONObject) item;
// 转换字段数据
columnsObj.put(column.getString("field"), column);
});
//设置转换后的数据
tableInfo.put("columns", columnsObj);
return tableInfo;
}
// 获取用户信息
public UserInfo getUserInfo() {
// 获取当前的用户信息
HttpServletRequest request = SpringWebUtil.getRequest();
RequestContext rc = ContextUtil.getRequestContext(request);
return rc.getUserInfo();
}
// 插入日志
public void addLog(String tableName, String method, String data) {
OperationLogs operationLogs = new OperationLogs();
operationLogs.setOperationDate(new Date());
operationLogs.setTableName(tableName);
operationLogs.setOperationType(method);
operationLogs.setOperationText(data);
operationLogs.setFid(UUID.randomUUID().toString());
UserInfo user = this.getUserInfo();
operationLogs.setOperationUserId(user.getId());
operationLogs.setOperationUserName(user.getName());
this.operationLogsMapper.insert(operationLogs);
}
添加插入/修改事件
添加插入、修改数据事件,监听 main 模块 contact 数据集中数据的插入和修改,详细代码如下:
@EventListener(condition = "#event.moduleName == 'main' && #event.method == 'upsert' && #event.tableName=='main_contact'")
public void upsert(DbUpsertEvent event) throws Exception {
if (event.getStatus() != Status.START)
return;
// 获取服务名
String serviceName = ContextUtil.getServiceName();
// 获取表字段信息
JSONObject tableInfoObj = this.getColumnInfo(event.getDataModelName());
JSONObject primaryProps = tableInfoObj.getJSONObject("primaryProps");
JSONObject columnsObj = tableInfoObj.getJSONObject("columns");
// 获取插入/更新的数据
JSONArray newData = event.getData();
// 兼容多条操作数据
newData.forEach(data -> {
JSONObject newDataObj = (JSONObject) data;
// 查询之前数据
DbrestWrapper<?> wrapperSaler = (DbrestWrapper<?>) new DbrestWrapper<String>(serviceName, "main",event.getDataModelName());
// 获取主键数据
List<String> primaryLable = new ArrayList<>();
// 兼容多字段主键查询
primaryProps.keySet().forEach(primaryColumn -> {
// 设置主键查询条件
wrapperSaler.eq(primaryColumn, newDataObj.getString(primaryColumn));
// 设置主键数据
JSONObject columnObj = columnsObj.getJSONObject(primaryColumn);
primaryLable.add(columnObj.getOrDefault("label", primaryColumn).toString() + "=" + newDataObj.getString(primaryColumn));
});
String queryData = DbrestUtil.get(wrapperSaler, null).getResult();
JSONArray oldDataList = JSON.parseArray(queryData);
// 判断新增还是修改及操作字段名称
StringBuilder str = new StringBuilder();
if (oldDataList.size() == 0) {
JSONObject cnData = new JSONObject();
// 字段数据转换
newDataObj.keySet().forEach(key -> {
JSONObject columnObj = columnsObj.getJSONObject(key);
if (columnObj == null) {
columnObj = new JSONObject();
}
cnData.put(columnObj.getOrDefault("label", key).toString(), newDataObj.get(key));
});
str.append(JSON.toJSONString(cnData));
} else {
JSONObject oldData = oldDataList.getJSONObject(0);
List<String> changeData = new ArrayList<String>();
// 比对获取差异数据
oldData.keySet().forEach(key -> {
if (!oldData.getOrDefault(key, "").equals(newDataObj.getOrDefault(key, ""))) {
JSONObject columnObj = columnsObj.getJSONObject(key);
if (columnObj == null) {
columnObj = new JSONObject();
}
changeData.add(String.format("%s:%s --> %s", columnObj.getOrDefault("label", key),
oldData.get(key), newDataObj.get(key)));
}
});
str.append("数据[").append(String.join(",", primaryLable)).append("]{")
.append(String.join(",", changeData)).append("}");
}
this.addLog(tableInfoObj.getString("label"), oldDataList.size() == 0 ? "新增" : "修改", str.toString());
});
}
添加删除事件
添加删除数据事件,监听 main 模块 contact 数据集中数据的删除,详细代码如下:
@EventListener(condition = "#event.moduleName == 'main' && #event.method == 'delete' && #event.tableName=='main_contact'")
public void delete(DbDeleteEvent event) throws Exception {
if (event.getStatus() != Status.START)
return;
// 获取表字段信息
JSONObject tableInfoObj = this.getColumnInfo(event.getDataModelName());
JSONObject columnsObj = tableInfoObj.getJSONObject("columns");
// 获取删除条件
List<String> condition = new ArrayList<>();
List<String> conditionFields = event.getConditionFields();
//过滤null数据
conditionFields=conditionFields.stream().filter(Objects::nonNull).collect(Collectors.toList());
for (int i = 0; i < conditionFields.size(); i++) {
JSONObject columnObj = columnsObj.getJSONObject(conditionFields.get(i));
if (columnObj == null) {
columnObj = new JSONObject();
}
condition.add(columnObj.getOrDefault("label", conditionFields.get(i)) + "="
+ JSON.toJSONString(event.getParamValues().get(i)));
}
this.addLog(tableInfoObj.getString("label"), "删除", JSON.toJSONString(condition));
}
添加查询事件
添加查询数据事件,监听 main 模块 contact 数据集的数据查询,详细代码如下:
@EventListener(condition = "#event.moduleName == 'main' && #event.method == 'query' && #event.tableName=='main_contact'")
public void query(DbQueryEvent event) throws Exception {
if (event.getStatus() != Status.START)
return;
// 获取表字段信息
JSONObject tableInfoObj = this.getColumnInfo(event.getDataModelName());
JSONObject primaryProps = tableInfoObj.getJSONObject("primaryProps");
JSONObject columnsObj = tableInfoObj.getJSONObject("columns");
// 获取查询参数
List<String> condition = new ArrayList<>();
List<String> conditionFields = event.getConditionFields();
//过滤null数据
conditionFields=conditionFields.stream().filter(Objects::nonNull).collect(Collectors.toList());
// 过滤按照主键进行查询数据
if(conditionFields.size()==primaryProps.keySet().size()) {
boolean isPrimaryQuery = true;
for (String fields : conditionFields) {
isPrimaryQuery = isPrimaryQuery && primaryProps.keySet().contains(fields);
}
if (isPrimaryQuery) {
return;
}
}
// 处理其他查询条件数据
for (int i = 0; i < conditionFields.size(); i++) {
JSONObject columnObj = columnsObj.getJSONObject(conditionFields.get(i));
if (columnObj == null) {
columnObj = new JSONObject();
}
condition.add(columnObj.getOrDefault("label", conditionFields.get(i)) + "="
+ JSON.toJSONString(event.getParamValues().get(i)));
}
//有查询条件进行记录
if (condition.size() > 0) {
this.addLog(tableInfoObj.getString("label"), "查询", String.join(",", condition));
}
}
完成上述代码后,已完成数据集操作监听,后续有相关数据的增删改查,就会执行上面对应的监听事件。