概述
一般的业务系统都需要记录用户的操作行为和监控用户对数据的改动,以便事后监察或分析问题原因。jeecg 框架已默认提供了“系统日志”和“数据日志”这两个模块,下面让我们来看一下它是怎么实现的吧。
系统日志
首先,让我们看一下最终的展示效果:
系统日志.png
从截图可以看出,系统日志记录了用户的行为类型、日志内容、IP、用户信息、浏览器、操作时间等数据。然后从代码分析得知,这些数据都保存在 t_s_log 这张表中。接下来,让我们跟着代码看看是怎么获取数据并插入到数据库的。
以用户退出的日志举例,在 LoginController.logout( ) 方法里调用了 SystemService.addLog( ) 方法,传入了“日志内容”、“日志类型”、“日志级别”这三个数据,不过开发人员把“日志类型”和“日志级别”这两个参数搞反了(v3.7.2版本),由于在数据库都是用的数字保存,在界面上转义回文字时也能有对应的值,也不影响查看,只是大家留意有这个问题即可。而在 addLog( ) 方法里,代码构造了一个 TSLog 对象,然后把各字段的值保存进去,用户的IP、浏览器信息可从 Request 对象获取,用户信息则从 session 中获取。最后,调用对应的 Dao 对象方法,把实体对象保存到数据库里。
从代码分析可以看出,jeecg 框架对行为日志的记录是直接嵌入到业务代码里的,要记录哪些类型的日志,需要在调用的对应业务方法里增加 addLog( ) 方法的调用,并定义好日志类型的 code 和日志内容格式。这种实现方式可能开发人员在写代码时思路会比较顺畅,但缺点是不灵活且重复代码较多。
数据日志
让我们再看一下数据日志的实现。同样,先来一张截图看下展示效果:
数据日志.png
数据日志记录下了数据所在的表名、数据id、数据版本号、数据内容、创建人等内容,保存在 t_s_data_log 这张表里。其中,数据内容是以 json 格式序列化的字符串。当选择两条同一张表的数据时,还提供了“数据比较”功能,如果是同一个数据id的不同版本数据,就可以看出这两个版本的数据差异了。
下面来分析一下代码实现,在 SystemService 类提供了 public void addDataLog(String tableName, String dataId, String dataContent);
方法,传入表名、数据id和 json 格式的数据内容即可插入数据。再看下 SystemServiceImpl 实现类里该方法的实现逻辑,先从 t_s_data_log 表根据表名和数据id查询出当前最大的版本id,然后把版本id加1,构造出一个新的数据实体,然后持久化到数据库里,便完成了。经过代码搜索,框架里已有模块的代码里并没有调用 addDataLog( ) 方法的地方,但应用的方式应该跟行为日志的调用方式一致,在对数据做增删改时,都可以调用方法插入一条数据变更日志。
一些思考
关于行为日志和数据日志的记录,我在以前的公司使用的框架也有类似的封装,但相较于 jeecg 框架的实现,会更灵活些。我们是采用 AOP 的方式对业务方法做编织,实现业务与日志的解耦,然后通过配置文件配置需要采集日志的业务方法,并配置用来标识的 code 及一些描述信息。而对数据日志的记录,则是在jdbc层对要执行的 sql 做拦截,类似 druid 连接池对 sql 的解析,得到本次操作要修改的数据,然后插入到数据库。
以上方式对日志的采集,都是为了在一套系统内完成所有的事情,难免会对业务系统的正常运行造成性能影响或是逻辑上的侵入。而现在互联网公司的做法,一般对行为日志的采集交由前端统一上报到日志系统,而对数据日志的采集则是根据交易流水号,打印详细的交易日志,然后用日志分析系统采集日志文件数据,做到业务系统与日志系统相隔离。
没有最好的方案,只有最适合的方案。开发时应根据实际需求的规模、工期、要求等等因素,选取最适合项目的技术方案。
领取专属 10元无门槛券
私享最新 技术干货