# 数据生命周期

# 概述

数据生命周期日志保存类型主要包含:单表(包含单个字段)的日志,关联表的日志,导入的日志,父子表的日志,自定义日志 ,在上述五中日志类型中所用到注解或者实体有:@Desensitized 脱敏注解,@TableMainField主表标识注解,LogProperty对象, Gather对象,BindProperty对象,BussinessLogEntity对象

# 日志BussinessLogUtils工具类

日志工具类方法说明

方法名        方法说明
polishingProperty 封装LogProperty类中的属性值,可以省去手动添加日志时的一部分属性的配置
processData(List beforData, List afterData,LogProperty logProperty) 用于非导入类型的数据,进行日志的插入操作,需要传入之前数据,之后数据,以及日志的属性对象;如果是关联关系类型的属性,beforData与afterData需要是BindProperty的集合
processData(LogProperty logProperty,Gather) 用于导入类型的数据,进行日志的插入操作
saveBussinessLog(BussinessLogEntity log) 插入日志,业务系统单独维护日志实体内容,此方法只提供保存日志

# 日志保存类型

日志数据类型操作主要分为:

# 1.单表(包含单个字段)的日志

将前后数据组装成new,ord两个对象(对象格式允许为JSONObject,Map,entity等)以后调用processData(List beforData, List afterData,LogProperty logProperty)方法插入日志;主键id必传

//对象添加
LogProperty logProperty=new LogProperty();
logProperty.setType(BussinessLogEnum.INSERT.getCode());
logProperty.setSDateTime(System.currentTimeMillis());
LogProperty logProp = BussinessLogUtils.polishingProperty(logProperty, Config.class);
BussinessLogUtils.processData(new ArrayList(), Arrays.asList(config),logProp);

//更新字段

PagePreset pagePreset = this.selectById(id);
LogProperty logProperty=new LogProperty();
logProperty.setType(BussinessLogEnum.UPDATE.getCode());
logProperty.setSDateTime(System.currentTimeMillis());
//如果需要不显示某一些字段可以排除
logProperty.setIgnoreFields("name,code");
LogProperty logProp = BussinessLogUtils.polishingProperty(logProperty, PagePreset.class);
//更新的字段放进对象中
JSONObject newObject=new JSONObject();
newObject.putOpt("id",pagePreset.getId());
newObject.putOpt("actived",actived);
//旧值可以封装传递也可以直接查询出传递
BussinessLogUtils.processData(Arrays.asList(pagePreset), Arrays.asList(newObject),logProp);

# 2.关联表的日志

需要将修改之前的数据与修改之后的数据封装到BindProperty对象中;调用processData(List beforData, List afterData,LogProperty logProperty)方法插入日志;logProperty中的BusinessId必传
  // 新资源权限记录,用于日志数据记录 
   .....
  //新的资源集合
  List<BindProperty> afterList = listToMap(resourceIdList);
  // 原资源权限记录,用于日志数据记录
  List<BindProperty> beforeList = listToMap(oldResourceIdList);
  LogProperty property=new LogProperty();
  property.setBusinessId(roleId);
  property.setSDateTime(System.currentTimeMillis());
  property.setTitle(role.getName()+"(资源授权)");
  property.setType(BussinessLogEnum.BIND.getCode());
  //polishingProperty传入的是主表中的类
  BussinessLogUtils.processData(beforeList,afterList,BussinessLogUtils.polishingProperty(property,Role.class));

# 3.导入的日志

需要将数据封装到Gather中;调用processData(LogProperty logProperty,Gather)方法插入日志
 ...
 LogProperty property=new LogProperty();
 property.setSDateTime(System.currentTimeMillis());
 property.setType(BussinessLogEnum.IMPORT.getCode());
 property=BussinessLogUtils.polishingProperty(property,Role.class);
 Gather gather = new Gather();
 gather.setType(UploadTypeEnum.UPDATE.getCode());
 gather.setTotal(newList.size());
 gather.setSuccess(sum);
 BussinessLogUtils.processData(property,gather);

# 4.父子表的日志

如果是父子的日志类型需要将LogProperty 中的isSkirt设置为true;同时需要搭配TableMainField注解使用;需要传实体的完整对象。

   LogProperty logProperty=new LogProperty();
   logProperty.setType(BussinessLogEnum.INSERT.getCode());
   logProperty.setSDateTime(System.currentTimeMillis());
   logProperty.setIsSkirt(true);//设置为true以后在父表的数据日志中就可以看到子表更新的内容
   LogProperty logProp = BussinessLogUtils.polishingProperty(logProperty, PageColumn.class);
   BussinessLogUtils.processData(new ArrayList(), Arrays.asList(column),logProp);
    ------------------------------------------
    //子实体中的父字段加上注解
    @TableMainField(tableClass = PagePreset.class)
    private String pageId;

# 5.自定义日志

保存,需封装业务日志实体,调用saveBussinessLog方法。

       BussinessLogEntity entity = new BussinessLogEntity();
        entity.setEntityCode("com.dhcc.user");
        entity.setTableName("用户管理");
        ....
        BussinessLogUtils.saveBussinessLog(entity);

# 注意

不管哪一个种类型的日志都需要往LogProperty中添加必要的参数:

type:类型见BaseBusinessLogEnum()

sDateTime:开始时间戳

key:默认为id

BusinessId:在关联时必须传递;主表的id例如用户关联角色BusinessId则为用户id.

title:非关联表如果不传时会根据describeField的字段名称拼接如果describeField为空则默认为name

其他参数可以通过工具类的polishingProperty方法获取

如果使用数据脱敏时需要在相应的字段上加上注解

   @ApiModelProperty(value = "密码")
    @TableField("password")
    @Desensitized(left = 0,right = 0,digit = 6)
    private String password;

提示

1.工具类polishingProperty方法中的参数有部分取自注解TableName,ApiModel;如果使用此方法时需在实体中维护这两个注解

2.数据脱敏时截取长度应小于实际长度,左侧或者右侧脱敏截取长度应在合理范围内截取。

# 日志注解,对象参数描述

# 注解@Desensitized

应用在实体字段中,用于字段数据的脱敏

 /**
     * 脱敏左侧保留位置
     * @return
     */
    int left() default 0;
    /**
     * 脱敏右侧保留位置
     * @return
     */
    int right() default 1;

    /**
     * 截取的长度默认127为不用截取
     * @return
     */
    int digit() default 127;

# 注解@TableMainField

主表字段标识,标注在子表的外键字段上

   /**
    *@Description: 主表类

    * @return: java.lang.String
    *@auth:whh
    *@date 2022/5/20
     **/
    Class tableClass();

    /**
    *@Description:主表描述字段

    * @return: java.lang.String
    *@auth:whh
    *@date 2022/6/2
     **/
    String describeField() default "name";

# 对象LogProperty

封装日志属性内容对象

  @ApiModelProperty("开始时间")
    private  long sDateTime;

    @ApiModelProperty("实体编码")
    private  String entityCode;

    @ApiModelProperty("约束键值(id,code等)")
    private  String key;

    @ApiModelProperty("类型见BaseBusinessLogEnum")
    private  String type;

    private  String ip;

    @ApiModelProperty("访问路径")
    private  String loginLocation;

    @ApiModelProperty("实体名称")
    private  String entityName;

    @ApiModelProperty("表名称")
    private  String tableName;

    @ApiModelProperty("租户id")
    private  String tentantId;


    @ApiModelProperty("需要忽略的字段")
    private  String ignoreFields;

    @ApiModelProperty("spel表达式")
    private  String expression;

    @ApiModelProperty("是否存在父子关系")
    private  Boolean isSkirt;

    @ApiModelProperty("业务数据id在做关联表的日志时使用")
    private  String businessId;

    @ApiModelProperty("对象描述")
    private  String title;

    @ApiModelProperty("描述字段用于title空时填充title")
    private  String describeField;

# 对象Gather

导入数据统计类用于导入时传参

    @ApiModelProperty("总数")
    private int total;
    @ApiModelProperty("成功")
    private int success;
    @ApiModelProperty("操作类型")
    private String type;

# 对象BindProperty

用于关联类型的操作数据封装

 /**
    *@Description:  唯一标识
    * @param null:
    * @return: null
    *@auth:whh
    *@date 2022/6/2
     **/
    private  String identify;
    /**
    *@Description:  描述
    * @param null:
    * @return: null
    *@auth:whh
    *@date 2022/6/2
     **/
    private  String describe;

# 对象BussinessLogEntity

储存各个类型日志的数据表

    @ApiModelProperty(value = "业务的名称")
    @TableField("title")
    private String title;

    @ApiModelProperty(value = "实体名称")
    @TableField("entity_name")
    private String entityName;

    @ApiModelProperty(value = "实体类名")
    @TableField("entity_code")
    private String entityCode;

    @ApiModelProperty(value = "实体表名")
    @TableField("table_name")
    private String tableName;

    @ApiModelProperty(value = "操作类型")
    @TableField("type")

    private String type;

    @ApiModelProperty(value = "业务id")
    @TableField("bussiness_id")
    private String bussinessId;


    @ApiModelProperty(value = "耗时")
    @TableField("take_up_time")
    private Long takeUpTime;

    @ApiModelProperty(value = "IP")
    @TableField("ip")
    private String ip;

    @ApiModelProperty(value = "服务IP")
    @TableField("service_ip")
    private String serviceIp;

    @ApiModelProperty(value = "登录地址")
    @TableField("login_location")
    private String loginLocation;

  • BussinessLogEnum枚举

    // 日志类型
    INSERT("insert","新增"),
    UPDATE("update","修改"),
    DELETE("delete","删除"),
    IMPORT("import","导入"),
    BIND("bind","关联");

# 查看数据生命周期

查看每个对象主体的生命周期,包含操作事件、操作类型、操作人、操作人ip、操作表、操作类描述及操作内容信息。如下图所示:

生命周期

# 查看数据日志

# 1. 概述

数据日志主要记录数据所有的操作过程,包含新增、修改、删除、导入等对数据做了变更的操作,查询除外。

# 2. 查询数据日志

数据日志可以根据对象描述、操作人、操作类型、操作时间来查询。默认查询最近一周的数据。如下图所示:

# 3. 查看日志详细

支持查看每条日志的详细信息。不同的操作类型显示的不一样。如下图所示:


提示
`删除`操作没有详细信息按钮

查看详情

新增编辑,展示对象的属性信息操作前后值

数据日志

导入,展示导入类型(包含添加新数据、添加并更新数据、更新数据)、导入总数、成功数。

数据日志

绑定,展示操作前后值的记录(主要用于授权、关联信息的变更记录)。

数据日志

# 4. 查看数据生命周期

用于查看每条数据完整的生命周期。如下图所示:


提示
导入操作没有生命周期按钮。