【操作日志】如何在一个SpringBoot+Mybatis的项目中设计一个自定义ChangeLog记录?

  设计一个业务改动信息时的自定义记录,例如新增、修改、删除数据等。并且记录的规则可以通过配置的方式控制。大家需要根据各自业务场景参考,欢迎讨论。伪代码如下:

实体类:

@TableName("tbl_user")
User{
    String id
    String name
    Integer age
    String addr
}

 



DAO层:

UserDao{
    getById(Long id);
    list(Wrapper wrapper);
}

 

 

自定义注解:

MybatisPropAnno{

  String value

  Class<?> daoClazz

}

 



Http接口请求参数:

SaveReq{
    @MybatisPropAnno(value="name", daoClazz = UserDao.class)
    String userName;
    @MybatisPropAnno(value="age", daoClazz = UserDao.class)
    Integer userAge;
}

UpdateReq{
    @MybatisPropAnno(value="id", daoClazz = UserDao.class)
    String userNo;
    @MybatisPropAnno(value="name", daoClazz = UserDao.class)
    String userName;
    @MybatisPropAnno(value="age", daoClazz = UserDao.class)
    Integer userAge;

    @MybatisPropAnno(value="id", daoClazz = DepartDao.class)
    String departId;
    String departAddress;
}

 



Http接口:

TestController{
    public void save(SaveReq saveReq){
        operTypeInheritedThreadLocal.set(Enum."添加数据");
        sthInheritedThreadLocal.set(saveReq);
    };

    public void update(UpdateReq updateReq){
        operTypeInheritedThreadLocal.set(Enum."更新数据");
        sthInheritedThreadLocal.set(updateReq);
    };

    @MybatisLogAnno("删除数据")
    public void delete(){};

    @MybatisLogAnno("查询数据")
    public void query(){};

    public void other(){};
}

 



SQL拦截器:

SqlInterceptor{
    public Object intercept(Mybatis param){    
        OperType operType = operTypeInheritedThreadLocal.get
        if(operType == null){
            return ;
        }
        
        // insert/update/delete/select
        String type = param.getSqlType();
        if(operType == select){
            return ;
        }
        
        String sql = param.getSql();
        
        String tableName = sql.getTableName();

        List<Field> fields = Reflect.getFields(sthInheritedThreadLocal.get());

        for(Field field : fields){
            MybatisPropAnno propAnno = field.getAnnotation(MybatisPropAnno);
            if(propAnno  == null){
                continue;
            }
            if(propAnno.getDaoClazz.getEntity.getTableName.equals(tableName )){
                User oldUser = new JSONObject();
                User newUser = new JSONObject();
                if(type == insert){
                    oldUser = new JSONObject();
                    newUser = getInsertInfo(sql);
                }

                if(type == update){
                    oldUser = SpringContext.get(daoClazz).getById(field.value());
                    newUser = getUpdateInfo(sql);
                    insertChangeLog(new JSONObject(), JSON.toJson(newUser));
                }
                if(type == delete){
                    oldUser = SpringContext.get(daoClazz).getById(field.value());
                    newUser = new JSONObject();
                }

                insertChangeLog(operType, traceId, oldUser, newUser);
                break;
            }
        }
    }
}

 



Spring切面:

SpringAop {
    public Object doAround(){
        operTypeInheritedThreadLocal.remove
    }
}

 



数据库设计:
Table:dc_change_log
id    changeTime    changeType    traceId    oldInfo        newInfo        httpMethod        table        operator    changeDesc
1    2020-01-01    添加用户        123    {}        {"name":"lil"}    com.xx.TestCtrl.saveUser    tbl_user        admin    descxxxxxxxxxxxx
2    2020-01-01    修改用户        124    {"name":"lil"}    {"name":"a"}    com.xx.TestCtrl.updateUser    tbl_user        admin    descxxxxxxxxxxxx
3    2020-01-01    修改用户        124    {"addr":"南山"}    {"addr":"福田"}    com.xx.TestCtrl.updateUser    tbl_department    admin    descxxxxxxxxxxxx

Table:dc_change_rule
id    httpMethod        table        showRule
1    com.xx.TestCtrl.saveUser    tbl_user        [{"propKey":"name", "propDesc":"name detail info"}]
1    com.xx.TestCtrl.updateUser    tbl_user        [{"propKey":"name", "propDesc":"name detail info"}]
1    com.xx.TestCtrl.updateUser    tbl_department    [{"propKey":"addr", "propDesc":"addr detail info"}]

热门相关:最强狂兵   学霸女神超给力   最强反套路系统   战神   重生当学神,又又又考第一了!