当前位置: 首页 > news >正文

SpringBoot使用 AOP 实现自定义日志记录并保存在Mysql

本文主要介绍在 Spring Boot 中使用 AOP 实现自定义日志记录并保存在 Mysql 的方法。先阐述记录日志的重要性及传统方式的弊端,提出新方式,即通过创建自定义注解、切面类等,将重要日志存到数据库,还给出了创建日志表、注解类、切面类及在代码中使用的具体步骤和存储结果。

记录日志的重要性

记录日志在开发中起着至关重要的作用。它不仅可以提高系统的可靠性、安全性和性能,还可以为故障排查、业务分析和合规要求提供支持。在Spring Boot中,我们通常使用日志框架如Logback、Log4j等进行日志记录。这些框架提供了灵活的配置选项和丰富的日志级别和输出格式,使得日志记录变得方便且易于管理。

传统记录日志的弊端

然而,传统的日志记录方式通常是将日志记录在text文本中,并且会定期删除。这种方式存在一些局限性,比如无法轻松地获取很久之前的日志、进行日志数据的统计和分析整理、实现数据的关联和追踪等功能。此外,对于一些重要的日志,我们可能希望具备更高的安全性和隐私性,或者需要对日志数据进行备份和恢复,甚至希望能够实现日志数据的共享。这就需要我们思考一种新的记录日志的方式。
在实际开发中,我们通常需要更多的功能来满足日志记录的需求:

  • 查询历史日志:我们可能需要获取很久之前的日志数据,以便进行历史记录的查看和分析。
  • 统计和分析日志数据:对日志数据进行统计和整理,以便进行业务分析和系统性能优化。
  • 数据关联和追踪:需要将日志数据与其他数据进行关联,以实现对系统操作和业务流程的追踪和监控。
  • 提高日志的安全性和隐私性:确保敏感信息不被泄露,对日志数据进行安全加密和权限控制。
  • 日志数据备份和恢复:对重要的日志数据进行定期备份,以便在系统故障或数据丢失时进行快速恢复。
  • 数据共享:需要能够方便地与其他系统或团队共享和交换日志数据,以实现更全面的系统监控和分析。

以上这些功能是我们在日志记录过程中经常会遇到的需求,对于如何实现这些功能,我们需要综合考虑技术、业务和安全等方面的因素,以便为系统的可靠性、安全性和性能提供更全面的支持。

使用AOP将日志存储到Mysql中

一种解决方案是使用AOP(面向切面编程)结合自定义注解来实现日志存储。AOP允许我们在程序执行的特定点织入代码,而自定义注解则可用于标记需要记录日志的方法。通过这种方式,我们可以实现灵活且精准的日志记录,并在需要时将重要的日志存储到数据库中。
为了实现这一目标,我们可以按照以下步骤进行:
首先,创建一个自定义注解,用来标记需要记录日志的方法。该注解可以包含一些额外的信息,如操作描述等,以便于更详细地记录日志。
其次,创建一个切面类,该类包含切入点和通知。在切面类中,我们可以定义通知,在方法执行前后、抛出异常时等特定时刻进行日志记录。在通知中,我们可以获取方法的参数、返回值等信息,并将这些信息记录到数据库中。
在需要记录日志的方法上添加自定义注解。通过在方法上添加自定义注解,我们可以指示AOP在执行该方法时进行日志记录,并将日志存储到数据库中。
通过以上步骤,我们就可以实现对日志存储的优化和扩展。这种基于AOP和自定义注解的日志记录方式具有很多优点,包括灵活性高、精细化的记录方式、易于管理和扩展等。同时,通过将重要的日志存储到数据库中,我们可以轻松地获取历史日志、进行统计分析、实现数据关联和追踪等功能。

SpringBoot 整合 AOP

Spring Boot 整合Aop

我们需要实现的目的

    1. 自定义日志记录,包括记录系统接口的日志以及保存到数据库。 (@Log 注解标注需要记录日志的方法或类)
    1. 创建注解 @Log 来指定需要记录的模块、功能等信息,以便进行日志记录。
  • 30 创建切面类 LogAspect,用于记录请求信息、当前用户信息、错误信息等,并将这些信息保存到数据库中

步骤

1、创建一个all_data_log自定义日志表

主要定义了操作日志的一些基本的信息,用来对我们AOP自定义的日志进行存储。

CREATE TABLE `all_data_log` (`user_id` int DEFAULT NULL COMMENT '用户名',`url` varchar(512) DEFAULT NULL COMMENT '接口',`ip` varchar(100) DEFAULT NULL COMMENT 'ip地址',`param` text COMMENT '接口参数',`time` datetime DEFAULT NULL COMMENT '时间',`method` varchar(100) DEFAULT NULL COMMENT '方法',`project` varchar(100) DEFAULT NULL COMMENT '项目'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='自定义日志表';
2、创建一个注解类 Log

创建一个注解类 Log,定义在类和方法上的注解。注解中可以包括模块、功能、操作人类别、是否保存请求和响应参数等信息。

/*** 自定义操作日志记录注解*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{/*** 模块 */public String title() default "";/*** 功能*/public BusinessType businessType() default BusinessType.OTHER;/*** 操作人类别*/public OperatorType operatorType() default OperatorType.MANAGE;/*** 是否保存请求的参数*/public boolean isSaveRequestData() default true;/*** 是否保存响应的参数*/public boolean isSaveResponseData() default true;
}
3. 创建一个切面类

创建一个切面类 LogAspect,用于记录系统接口的日志,并根据需要将日志信息保存到数据库中。在切面类中,可以根据注解中的信息记录请求的URL、方法、IP地址、参数、当前用户信息、错误信息等,并将这些信息保存到数据库中。

@Component
@Aspect
public class LogAspect {@Autowiredprivate RedisCache redisCache;@Autowiredprivate LogAspect logAspect;@Value("${token.header}")private String header;/*** 定义一个开关 可以随时关闭这个切面*/@Value("${aspect.switch}")private Boolean aBoolean;@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")public void doBefore(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {handle(joinPoint, jsonResult, null);}@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {handle(joinPoint, null, e);}private void handle(JoinPoint joinPoint, Object jsonResult, Exception e) {try {if (aBoolean) {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();HashMap<String, Object> map = new HashMap<>();// 获取请求的URLmap.put("url", request.getRequestURL().toString());// 获取请求的方法map.put("method", request.getMethod());// 获取请求的IP地址map.put("ip", request.getRemoteAddr());// 获取请求的参数Object[] args = joinPoint.getArgs();String params = "";try {if (args != null && args.length > 0) {for (Object arg : args) {if (arg instanceof MultipartFile[]) {params = "files";}}if (!params.equals("files")) {params = JSON.toJSONString(args[0]);}}} catch (Exception e1) {params = "参数解析失败";}map.put("params", params);// 获取当前的用户String token = request.getHeader(header);String userId = "";if (ObjectUtils.isNotEmpty(token)) {LoginUser loginUser = SecurityUtils.getLoginUser();if (ObjectUtils.isNotEmpty(loginUser)) {userId = loginUser.getUserId().toString();}}map.put("userId", userId);//记录错误信息if (e != null) {map.put("errorMsg", StringUtils.substring(e.getMessage(), 0, 2000));}//当前时间map.put("time", DateUtils.getTime());// 是否需要保存result,参数和值if (StringUtils.isNotNull(jsonResult)) {map.put("result", StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));}// 异步 保存数据库AsyncManager.me().execute(AsyncFactory.recordOper(map));}} catch (Exception exp) {exp.printStackTrace();}}
}
4. 如何在代码中使用

在需要记录日志的方法上使用 @Log 注解,指定相应的模块、功能等信息,以便进行日志记录。

/*** 新增商品*/
@Log(title = "新增商品", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody YdCommAttr ydCommAttr)
{return toAjax(ydCommAttrService.insertYdCommAttr(ydCommAttr));
}
5. 存储的结果

可以看到我们的切面完美的记录了我们想要记录的接口中的日志数据,以便于我们日后通过关系型数据库Musql去统计和分析这些数据。
在这里插入图片描述

相关文章:

SpringBoot使用 AOP 实现自定义日志记录并保存在Mysql

本文主要介绍在 Spring Boot 中使用 AOP 实现自定义日志记录并保存在 Mysql 的方法。先阐述记录日志的重要性及传统方式的弊端&#xff0c;提出新方式&#xff0c;即通过创建自定义注解、切面类等&#xff0c;将重要日志存到数据库&#xff0c;还给出了创建日志表、注解类、切面…...

谷歌开源最强天气预报AI模型 GenCast

谷歌 DeepMind 开源新一代天气预测 AI 模型 GenCast&#xff0c;GenCast 以最先进的精度预测天气和极端条件的风险 天气预报对人们生活和决策至关重要&#xff0c;但传统 NWP 模型存在不确定性&#xff0c;且计算资源需求大、运行慢。机器学习在天气预报中虽有进展&#xff0c;…...

C++打造局域网聊天室第十课: 客户端编程及数据发送

文章目录 前言一、补充内容&#xff0c;设置显示框换行二、客户端编程三、封装消息发送函数四、所处的身份状态总结 前言 C打造局域网聊天室第十课&#xff1a; 客户端编程及数据发送 一、补充内容&#xff0c;设置显示框换行 编辑框的显示内容默认是不会换行的&#xff0c;这…...

Nginx整合Lua脚本

Nginx-Lua Nginx整合Lua脚本 Lua环境搭建 下载地址 linux环境下 yum install lua安装后验证 lua -vLua脚本执行 lua xxx.luaNginx整合Lua nginx需要添加lua模块 嵌入内容 示例如下 修改nginx.conf如下 location /lua {default_type text/plain;content_by_lua ngx.sa…...

【C++】C++11 STL容器emplace方法原理剖析

在 C 11 STL 容器中&#xff0c;push/insert > emplace 新的方法&#xff0c;push 和 emplace 的区别在于&#xff1a; 1. push push 通常用于将一个元素添加到容器的末尾&#xff08;在 std::vector、std::deque 等序列容器中&#xff09;&#xff0c;或者在关联容器中插入…...

QT-简单视觉框架代码

文章目录 简介1. 整体架构2. 关键类功能概述3. 详细代码实现hikcameraworker.h 和 hikcameraworker.cpp&#xff08;海康相机工作线程类&#xff09;imageviewerwidget.h 和 imageviewerwidget.cpp&#xff08;图像查看部件类&#xff09;构造函数 ImageViewerWidget析构函数 ~…...

AI新书推荐:深度学习和大模型原理与实践(清华社)

本书简介 在这个信息爆炸、技术革新日新月异的时代&#xff0c;深度学习作为人工智能领域的重要分支&#xff0c;正引领着新一轮的技术革命。《深度学习和大模型原理与实践》一书&#xff0c;旨在为读者提供深度学习及其大模型技术的全面知识和实践应用的指南。 本书特色在于…...

[spring]处理器

我们可以通过spring来管理我们的类&#xff0c;之后我们可以通过spring的容器来获取我们所需要的Bean类对象。Spring的处理器是Spring对外开发的重要扩展点&#xff0c;它允许我们介入到Bean的整个实例化流程中来&#xff0c;可以动态添加、修改BeanDefinition、动态修改Bean 首…...

重温设计模式--中介者模式

中介者模式介绍 定义&#xff1a;中介者模式是一种行为设计模式&#xff0c;它通过引入一个中介者对象来封装一系列对象之间的交互。中介者使得各个对象之间不需要显式地相互引用&#xff0c;从而降低了它们之间的耦合度&#xff0c;并且可以更方便地对它们的交互进行管理和协调…...

重温设计模式--设计模式七大原则

文章目录 1、开闭原则&#xff08;Open - Closed Principle&#xff0c;OCP&#xff09;定义&#xff1a;示例&#xff1a;好处&#xff1a; 2、里氏替换原则&#xff08;Liskov Substitution Principle&#xff0c;LSP&#xff09;定义&#xff1a;示例&#xff1a;好处&#…...

LeetCode429周赛T4

最小化二进制字符串中最长相同子字符串的长度 在处理二进制字符串问题时&#xff0c;优化字符串结构以满足特定条件是一项常见的挑战。本文将探讨一个具体的问题&#xff1a;给定一个长度为 n 的二进制字符串 s 和一个整数 numOps&#xff0c;通过最多 numOps 次位翻转操作&am…...

详解MySQL在Windows上的安装

目录 查看电脑上是否安装了MySQL 下载安装MySQL 打开MySQL官网&#xff0c;找到DOWNLOADS 然后往下翻&#xff0c;找到MySQL Community(GPL) Downloads>> 然后找到MySQL Community Server 然后下载&#xff0c;选择No thanks,just start my download. 然后双击进行…...

【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】

本教程的知识点为&#xff1a;操作系统 1. 常见的操作系统 4. 小结 ls命令选项 2. 小结 mkdir和rm命令选项 1. mkdir命令选项 压缩和解压缩命令 1. 压缩格式的介绍 2. tar命令及选项的使用 3. zip和unzip命令及选项的使用 4. 小结 编辑器 vim 1. vim 的介绍 2. vim 的工作模式 …...

软件测试面试题和简历模板(面试前准备篇)

一、问题预测 1、让简单介绍下自己&#xff08;这个不用说了每次面试开场&#xff09; 面试官&#xff0c;你好&#xff0c;我叫xxx&#xff0c;xx年本科毕业&#xff0c;从事软件测试将近3年的时间。在此期间做过一些项目也积累过一些经验&#xff0c;能够独立地完成软件测试…...

Linux 基本使用和程序部署

1. Linux 环境搭建 1.1 环境搭建方式 主要有 4 种&#xff1a; 直接安装在物理机上。但是Linux桌面使用起来非常不友好&#xff0c;所以不建议。[不推荐]。使用虚拟机软件&#xff0c;将Linux搭建在虚拟机上。但是由于当前的虚拟机软件(如VMWare之类的)存在一些bug&#xff…...

uniapp微信小程序,使用fastadmin完成一个一键获取微信手机号的功能

前端部分 点击按钮&#xff0c;获取手机号 <button open-type"getPhoneNumber" getphonenumber"bindGetPhoneNumber" hover-class"none"class"btn-purity">一键获取</button> 传入openid和code bindGetPhoneNumber(e) …...

CSS系列(27)- 图形与滤镜详解

前端技术探索系列&#xff1a;CSS 图形与滤镜详解 &#x1f3a8; 致读者&#xff1a;探索CSS的艺术表现力 &#x1f44b; 前端开发者们&#xff0c; 今天我们将深入探讨 CSS 图形和滤镜效果&#xff0c;学习如何创建引人注目的视觉效果。 基础图形 &#x1f680; 几何形状…...

Docker 技术系列之安装多版本Mysql5.6和Mysql5.7

image 大家好&#xff0c;后面的就不是关于MAC专有的内容&#xff0c;基本是跟Java环境&#xff0c;基础技术方面有关。所以这个教程对于在linux系统还是macOS都是通用的&#xff0c;不用担心。 上一篇&#xff0c;我们安装好对应的Docker之后&#xff0c;感受到了它的便利。接…...

理解并使用Linux 内核中的 Tracepoint

理解并使用Linux 内核中的 Tracepoint 1. 引言 1.1 为什么需要 Tracepoint&#xff1f; 在内核调试与性能分析中&#xff0c;传统的 printk 方法虽然简单直接&#xff0c;但存在几个显著的局限性&#xff1a; 日志噪音&#xff1a;printk 会将所有输出无差别地记录到系统日…...

centos7中Gbase8s数据库安装,以及数据导入遇到的一系列问题

centos7中Gbase8s数据库安装&#xff0c;以及遇到的一系列问题 以下是我在centos7上安装gbase8s数据库遇到的一系列问题&#xff0c;包括数据库安装&#xff0c;数据导入&#xff0c;数据连接&#xff0c;不能完全作为标准&#xff0c;只可作为类似问题参考&#xff0c;有问题…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...