基于数据集事件监听实现数据日志记录

监听数据表中数据的增删改查,并记录对应表详细操作内容,运行效果如下图所示

图 9

特别说明

  • 由于使用后端 Java 数据集操作监听事件来记录操作日志,建议使用本地 ide 进行开发
  • 作为演示案例,为防止日志产生过多,本例只监听 contact 数据集,在实际使用中按需设置事件 condition 中的 event.tableName 参数

添加数据集

在 ide 中,添加“操作日志”数据集,包含表名、操作类型、操作内容、操作时间及操作人等列,存储用户操作记录。

图 1

添加事件处理类

在 main.common 下新增事件处理类 EventHandler.java

  • 引用操作日志 mapper 类

图 6

  • 新增表查询方法、获取用户方法及插入日志方法
   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));
       }

   }

完成上述代码后,已完成数据集操作监听,后续有相关数据的增删改查,就会执行上面对应的监听事件。

results matching ""

    No results matching ""