Spring-Aop实现操作日志收集

2023-11-09

最近刚换了份工作,这家公司主要做的是b端的产品,b端产品一般审计都比较严,所以免不了会有操作日志这个东西,但是我发现现在这家公司的操作日志都是这样收集的,看以下代码:

//记录操作日志 主子表分别添加
List<ContainerLogVO> containerLogVOS = BeanUtil.copyList(ContainerLogVO.class, listExecuteResult.getResult());
                            containerLogVOS.forEach(e -> {
                                e.setId(null);
                            });
                            ExecuteResult<List<ContainerLogVO>> listExecuteResult1 = containerLogService.addBatch(containerLogVOS);
                            if (!Constants.SUCCESS_CODE.equals(listExecuteResult1.getCode())) {
                                throw new Exception("容器日志保存异常");
                            }



//记录更新日志
GoodsBaseLogVO logVO = BeanUtil.copyPropertes(GoodsBaseLogVO.class, goodsBaseResult.getResult());
						logVO.setId(null);
						ExecuteResult<GoodsBaseLogVO> logVOExecuteResult = goodsBaseLogService.add(logVO);
						if(!Constants.SUCCESS_CODE.equals(logVOExecuteResult.getCode())){
							throw new Exception(logVOExecuteResult.getResultMessage());
						}

 随手粘了两处代码,这么写可不可以? 可以,但是太不面向对象了,O(∩_∩)O哈哈~

于是我就想着给他改造改造。

AOP的五大通知

先说aop的五个通知类型:

  • 前置通知 在目标方法执行前执行
  • 环绕通知 在目标方法执行之前和之后各执行一遍
  • 后置通知 在目标方法执行之后执行
  • 异常通知 在目标方法抛出异常后执行
  • 最终通知 在目标方法执行之后执行 目标方法无论是异常还是正常都会执行

如果方法出现异常,我这边是不需要记录操作日志的,所以我这边只选择后置通知就可以了(如果有特殊需求可以根据需要进行选择,也可以选择多个)

本次分享 只是给大家分享一个思路。

数据建模

 这个表属于方法与日志生成的映射关系表 在给大家看看对应的配置

 首先 methodName 我们根据aop是完全可以取到对应的方法名称和映射的mapping,methodInfo这个字段就是配置对应的日志 每个?就相当于一个占位符与后面的paramArr对应,channel和paramName一起说 拿id为1的举例 就相当于是取入参中的vo。大概配置表就是这么一个概念。

在看日志表:

 在看看日志表里面存储的信息

 具体实现

直接看代码

/**
 * @author Jacky
 * @create 2022-07-20-14:31
 */
@Component
@Aspect
public class UserLogAspect {

    private static final Logger log = LoggerFactory.getLogger(UserLogAspect.class);

    @Autowired
    private UserOperationLogExportService userOperationLogExportService;

    @Resource
    private UserColumnRelationDAO userColumnRelationDAO;

    @Autowired
    private MethodToLogExportService methodToLogExportService;

    @Pointcut("execution(* com.niu.wms.api..*.*(..))")
    public void allLog(){
    }

    @AfterReturning(value = "allLog()",returning = "ajaxInfo")
    public void saveLog(JoinPoint joinPoint, AjaxInfo ajaxInfo){
        // 拼接出对应的方法名以及映射的mapping
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取切入点所在的方法
        Method method = signature.getMethod();
        String methodName = method.getName();
        String allMapping = joinPoint.getTarget().getClass().getName().replace("Api", "").replace("Controller", "");
        String mapping = allMapping.substring(allMapping.lastIndexOf(".") + 1);
        // 根据对应的映射查询配置表 如配置表中无相关的配置则不记录
        MethodToLogVO methodToLogVO = methodToLogExportService.queryOneData(MethodToLogVO.builder().methodName(mapping + "/" + methodName).build()).getResult();
        if (Utility.isEmpty(methodToLogVO)){
            return;
        }
        String paramName = methodToLogVO.getParamName();
        JSONObject json = null;
        // 获取对应的参数 把对应的参数转成json格式
        if (methodToLogVO.getChannel().equals(0)){
            //参数名数组
            String[] parameters = signature.getParameterNames();
            //参数值
            Object[] args = joinPoint.getArgs();
            int voIndex = ArrayUtils.indexOf(parameters, paramName);
            if (voIndex==-1){
                return;
            }
            Object arg = args[voIndex];
            json = JSON.parseObject(JSON.toJSONString(arg));

        }else if (methodToLogVO.getChannel().equals(1)){
            Object data = ajaxInfo.getData();
            json = JSON.parseObject(JSON.toJSONString(data));
        }
        if (Utility.isEmpty(json)){
            return;
        }
        // 获取到参数之后进行占位符拼接赋值
        String paramArr = methodToLogVO.getParamArr();
        String[] split = paramArr.split(",");
        String methodInfo = methodToLogVO.getMethodInfo();
        String context = methodInfo;
        for (String s : split) {
             context = context.replaceFirst("\\?", json.getString(s));
        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String userId = request.getHeader("userId");
        Map map = userColumnRelationDAO.queryUserInfo(Long.valueOf(userId));
        String realIP = IpUtil.getRealIP(request);
        String userType1 = request.getHeader("userType");
        userType1 = userType1 == null ? "1": userType1;
        Integer userType = Integer.parseInt(userType1);
        String requestParam = JSON.toJSONString(joinPoint.getArgs());
        String response = JSON.toJSONString(ajaxInfo);
        StringBuilder result = new StringBuilder();
        
        if (ajaxInfo.getCode()!=0){
            result.append("失败:");
            result.append(ajaxInfo.getMsg());
        }else{
            result.append("成功");
        }
        ExecuteResult<UserOperationLogVO> save = userOperationLogExportService.add(UserOperationLogVO.builder()
                .userNumber(map.getOrDefault("userNumber",userId).toString())
                .userName(map.getOrDefault("userName",userId).toString())
                .logType(userType)
                .hostAddress(realIP)
                .operationContent(context)
                .request(requestParam)
                .response(response)
                .operationTime(new Date())
                .result(result.toString())
                .build());
        if (!save.getCode().equals(Constants.SUCCESS_CODE)){
            log.error("日志保存失败");
            log.error("错误信息:"+save.getResultMessage());
        }


    }
}

大概就是这么个东西,主要是分享一个思路,也有很多可以优化的地方,大家可以根据系统情况自行优化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring-Aop实现操作日志收集 的相关文章

随机推荐

  • 英语学习杂记

    这文章就没有什么逻辑了 仅仅是我觉得比较好的方法 应该时刻提醒我划重点的知识而已 1 有效的单词记忆法 上来先用艾宾浩斯记忆方法死记硬背一遍单词 在这一过程中 你会发现有些单词成为了你记忆中的盲点 就是记不下来 那么可以运用词根词缀联想记忆
  • jquery键盘事件及keycode大全

    jquery的键盘事件分为keypress keydown和keyup事件 一 键盘事件 1 keypress 事件 keypress 当按钮被按下时 会发生该事件 我们可以理解为按下并抬起同一个按键 2 keydown 事件 当按钮被按下
  • bug-mybatis中jdbcType类型DATE映射问题

    背景 昨天测试反馈问题说某个界面查询数据不准确 明明是在查询条件内的数据却查询不到 很诡异 我看了下 查询条件也只有创建时间这一个 如 2022 1 8 00 00 00 2022 1 8 23 59 59 但在那一天的数据却是死活出不来
  • 【Java笔记+踩坑】SpringBoot基础3——开发。热部署+配置高级+整合NoSQL/缓存/任务/邮件/监控

    导航 黑马Java笔记 踩坑汇总 JavaSE JavaWeb SSM SpringBoot 瑞吉外卖 SpringCloud SpringCloudAlibaba 黑马旅游 谷粒商城 目录 1 热部署 1 1 手动启动热部署 1 2 脱离
  • TensorFlow处理图片

    文章目录 TensorFlow与OpenCV 编码 编码 decode 解码 encode tf image decode gif tf image decode jpeg tf image encode jpeg tf image dec
  • mysql建立班级表_mysql数据表设计-班级表 学生表 老师表 课程表 成绩表

    mysql数据表设计 班级表 学生表 老师表 课程表 成绩表 image png Navicat Premium Data Transfer Source Server localhost Source Server Type MySQL
  • 【华为OD机试真题 python】区块链文件转储系统【2023 Q1

    题目描述 区块链文件转储系统 区块链底层存储是一个链式文件系统 由顺序的N个文件组成 每个文件的大小不一 依次为F1 F2 Fn 随着时间的推移 所占存储会越来越大 云平台考虑将区块链按文件转储到廉价的SATA盘 只有连续的区块链文件才能转
  • [34]如何设置PPT中的演讲者模式

    1 首先将投影设备或其它幻灯片输出设备连接到笔记本或 PC 上 在 Windows 7 中按Win 键 P 并选择扩展模式将当前笔记本或 PC 的显示器与投影显示输出设备设置为扩展模式 我们要演示的 PowerPoint 文档 在 Ribb
  • 深度学习论文阅读目标检测篇(七)中文版:YOLOv4《Optimal Speed and Accuracy of Object Detection》

    深度学习论文阅读目标检测篇 七 中英对照版 YOLOv4 Optimal Speed and Accuracy of Object Detection Abstract 摘要 1 Introduction 引言 2 Related work
  • android 语音自动播报,Android语音播报的两种简单实现

    a 两种方案 1 Android自带的语音播报 老版本手机Android6 0以下 不支持中文 2 讯飞语音播报封装 直接用 b 具体实现 一 Android自带的语音播报 查看手机是否支持中文语音播报 在测试的设备中打开 设置 gt 找到
  • linux下创建用户并且限定用户主目录

    linux下创建用户并且限定用户主目录 useradd d home users sport m sport passwd sport
  • Spring Security 最佳实践,看了必懂!

    今天来一篇 Spring Security 精讲 相信你看过之后能彻底搞懂 Spring Security Spring Security简介 Spring Security 是一种高度自定义的安全框架 利用 基于 SpringIOC DI
  • React中自定义事件this指向问题

    this是基于函数的执行环境 也就是上下文 绑定的 React组件生命周期函数中this的上下文就是组件实例 你必须谨慎对待 JSX 回调函数中的 this 类的自定义方法默认是不会绑定 this 的 首先调用 constructor 函数
  • 新项目报:Caused by: javax.net.ssl.SSLHandshakeException:

    新项目启动 报错 错误见下面三个图片 com mysql cj jdbc exceptions CommunicationsException Communications link failure The last packet sent
  • Git- 连接远程仓库

    如何使用Git 连接远程仓库呢 远程仓库 gt 一般指的是代码托管平台 那就先来瞅瞅三个较熟悉的版本 代码 托管服务平台 版本 代码 托管服务平台 码云 gitee com 是开源中国社区团队推出的基于Git的快速的 免费的 稳定的在线代码
  • build kernel :missing symbol table

    https www spinics net lists kernel msg3797871 html
  • 【茗创科技】如何看待心理学实验中的数据缺失?

    大家好 这里是 茗创科技 茗创科技专注于脑科学数据处理 涵盖 EEG ERP fMRI 结构像 DTI ASL FNIRS 等 欢迎留言讨论及转发推荐 也欢迎了解茗创科技的脑电课程 数据处理服务及脑科学工作站销售业务 可添加我们的工程师 M
  • robot framework 初学--打开浏览器

    在TesterHome看到一篇文章后 跟着做了一遍 源地址https testerhome com topics 10447 这里是我个人操作之后的一些疑问和解决方法 1 Robot是否是以键值对的形式存在呢 A 我实在是太天真了 只是看到
  • 数字化时代10:从我国经济建设目标看社会产品形态的变化

    摘要 从我国经济建设目标看产品的形态变化 从物质到精神 从实体到虚拟 物体到人自身 看到财富形态变化的端倪 随着物质产品的极大丰富 物质产品的新的价值 不在物质本身 即不是在物质产品原先的 固有的使用价值 而是在于它作为某种精神产品的物质承
  • Spring-Aop实现操作日志收集

    最近刚换了份工作 这家公司主要做的是b端的产品 b端产品一般审计都比较严 所以免不了会有操作日志这个东西 但是我发现现在这家公司的操作日志都是这样收集的 看以下代码 记录操作日志 主子表分别添加 List