目的:对特定字段的值变更进行监测
实现思路:
- 猜测1:通过数据库里面写触发器和监听器来实现
- 猜测2:通过消息队列来实现
- 猜测3:通过AOP来实现
实际实现思路:
- 主要是通过监听器来实现对字段的监听,原想通过AOP来做这件事,后来因为牵涉较大,故改用简单易实现的方式来做。
核心组件:
- 自定义监听器实现hibernate提供的PostInsertEventListener,PostUpdateEventListener,PostDeleteEventListener接口类,分别监听不同的数据库操作类型,
如:新增、更新、删除。
推荐博客:http://www.iyujian.me/java/log-manager-by-PostInsertEventListener-PostUpdateEventListener-PostDeleteEventListener.html?nsukey=jYV1ZgysAvXxmBWEdQEMYxqB2Hcs4l1yYqmksaUhz8%2BC8ZwUqxv%2B6OJnGFsEmzDmCKaybClqIEAlwxkZ8hh86ZchLBXA4hJecwyEw80NSzkBciQzwuBp19pMphgWgOHWanuPxTcNCE6nxQW0zykhr0RvrsvyRV0jPiLwqg223vY4UwIAQkIHWno2tLfc4NgT35%2Bno0wfeiLpMLsLTlaYDQ%3D%3D
背景描述:
- 监听特定字段的增删改操作,并记录到日志管理表中间。因为项目还涉及到分布式的概念,所以要将该保存日志的功能抽到一个公共模块里面。在要进行日志监听的服务中实现监听器,如果监听到那么就发送请求,进行服务互调,调用公共模块的保存日志记录的方法。
- 踩坑:我在onPostInsert方法中做了对日志表的插入,导致了堆栈溢出。因为本身该方法就是一个监听新增操作事件,在新增里面新增操作,就会造成死循环。
- 约定俗成的规矩:要监听的表字段和表名要遵循驼峰法原则。
举例:以新增操作举例。
- 第一步:调用公共模块的查询日志管理表和日志管理字段表,得到要监听的表名和字段的集合,封装成Map<String param1,List<String> param2>格式,param1代表表名,param2代表字段集。
- 第二步:从方法的参数PostUpdateEvent event中获取对应的表名、字段名、字段值。
①获取表名:event.getEntity().getClass().getSimpleName();
②获取字段名:event.getPersister().getPropertyNames();
③获取字段值:event.getState();
- 第三步:根据本次操作的字段名称去匹配监听字段集合,如果在则调用基础服务的日志保存操作,如果不在则跳过。
- 备注:此处还引入了redis缓存,调用基础服务获取监听字段集,塞入缓存,在有效时间内不在进行跨服务调用,直接从缓存中获取所需的字段集。因为存储的是String类型的json,所以这里免不了还要使用到一些字符串截取的操作。
待完善点:在服务调用的时候,打印有效日志。需要考虑跨服务调用的时候,如果失败了,进行事务回滚。
优化点:
1、因为监听器实现的业务逻辑对每个服务来说是不变的,所以不该每个服务写一遍,应该将其打包成jar,以开关的形式直接嵌入到需要日志服务记录的服务中。
2、基于Eclipse的打包参照博客:https://blog.csdn.net/weixin_44333583/article/details/90439633
3、打完嵌入之后发现监听器的日志没有被输出,证明没有被Spring扫描到。那么需要搜索Spring如何去扫描jar包中的注解类。
参照博客:https://www.cnblogs.com/skyme/archive/2011/08/11/2134918.html
至此大功告成,哪里需要哪里引。学习之路很漫长,有时候一步不能完成,就分多步来实现。
2019-12-02