Springboot使用Aop保存接口请求日志到mysql
1、添加aop依赖
<!-- aop日志 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
2、新建接口保存数据库的实体类RequestLog.java
package com.example.springboot.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;/*** <p>* 请求日志* </p>** @author Sca_jie* @since 2023-09-28*/
@Getter
@Setter
@TableName("request_log")
public class RequestLog implements Serializable {private static final long serialVersionUID = 1L;// 主键-自增@TableId(value = "number", type = IdType.AUTO)private Integer number;// 用户账号private String id;// 携带tokenprivate String token;// 接口路径private String url;// 请求类型private String method;// 携带参数private String params;// ip地址private String ip;// 结果private String result;// 接口发起时间private LocalDateTime startDate;// 接口结束时间private LocalDateTime endDate;// 响应耗时private String responseTime;
}
3、新建一个注解RequestLogAnnotation.java
package com.example.springboot.annotation;import java.lang.annotation.*;/*** 请求记录日志注解*/
@Target({ElementType.TYPE, ElementType.METHOD}) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface RequestLogAnnotation {String value() default "";
}
4、(核心)新建aop面切类RequestLogAspect.java拦截请求并保存日志
package com.example.springboot.common;import cn.hutool.core.net.NetUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.springboot.annotation.RequestLogAnnotation;
import com.example.springboot.entity.RequestLog;
import com.example.springboot.mapper.RequestLogMapper;
import com.example.springboot.utils.CookieUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.time.LocalDateTime;/*** 日志记录**/
@Aspect
@Component
public class RequestLogAspect {@Autowired(required = false)RequestLogMapper requestLogMapper;@Pointcut("@annotation(com.example.springboot.annotation.RequestLogAnnotation)")public void logPointCut() {}// 请求的开始处理时间(不同类型)Long startTime = null;LocalDateTime startDate;@Before("logPointCut()")public void beforeRequest() {startTime = System.currentTimeMillis();startDate = LocalDateTime.now();}@AfterReturning(value = "logPointCut()", returning = "result")public void saveLog(JoinPoint joinPoint, Object result) {// 获取请求头ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();HttpServletResponse response = requestAttributes.getResponse();//从切面织入点处通过反射机制获取织入点处的方法MethodSignature signature = (MethodSignature) joinPoint.getSignature();//获取切入点所在的方法Method method = signature.getMethod();// 初始化日志表的实体类RequestLog requestLog = new RequestLog();//获取操作RequestLogAnnotation requestLogAnnotation = method.getAnnotation(RequestLogAnnotation.class);// // 获取@SystemLogAnnotation(value = "用户登录")中的注解value
// if (systemLogAnnotation != null) {
// String value = systemLogAnnotation.value();
// requestLog.setSName(value);
// }// 获取cookiesCookie[] cookies = request.getCookies();if (cookies != null) {// 获取tokenfor(Cookie cookie : cookies){if(cookie.getName().equals("token")){requestLog.setToken(cookie.getValue());}}// 获取idString id = CookieUtil.getid(cookies);if (id != "" | id != null) {requestLog.setId(id);}}// 区分get和post获取参数String params = "{}";if (request.getMethod().equals("GET")) {params = JSONObject.toJSONString(request.getParameterMap());} else if (request.getMethod().equals("POST")) {params = JSONUtil.toJsonStr(joinPoint.getArgs());}// 用户IprequestLog.setIp(NetUtil.getLocalhostStr());// 接口请求类型requestLog.setMethod(request.getMethod());// 请求参数(区分get和post)requestLog.setParams(params);// 请求接口路径requestLog.setUrl(request.getRequestURI().toString());// 返回结果requestLog.setResult(JSONObject.toJSONString(result));// 请求开始时间requestLog.setStartDate(startDate);// 请求结束时间requestLog.setEndDate(LocalDateTime.now());// 请求共计时间(ms)requestLog.setResponseTime(String.valueOf(System.currentTimeMillis() - startTime));// 保存日志到mysqlrequestLogMapper.insert(requestLog);}
}
5、在对应接口添加注解@RequestLogAnnotation
@RequestLogAnnotation(value = "获取上传记录")@GetMapping("/getlist")public Result getlist (@RequestParam(required = false) String id) {if (id == null) {return Result.success(404, "参数缺失");} else {List<UploadLog> page = uploadLogService.getlist(id);return Result.success(200, page.toString());}}
效果如下

相关文章:
Springboot使用Aop保存接口请求日志到mysql
1、添加aop依赖 <!-- aop日志 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency> 2、新建接口保存数据库的实体类RequestLog.java package com.example…...
网络安全面试题汇总(附答案)
作为从业多年的网络安全工程师,我深知在面试过程中面试官所关注的重点及考察的技能点。网络安全作为当前信息技术领域中非常重要的一部分,对于每一个从事网络安全工作的人员来说,不仅需要掌握一定的技术能力,更需要具备全面的综合…...
Centos7安装kvm,配置虚拟机网络
1.安装软件包,禁用防火墙(非必须) yum -y install qemu-kvm libvirt virt-install 1)禁用防火墙(非必须) systemctl stop firewalld systemctl disable firewalld 2)禁用NetworkManager syst…...
Javascript文件上传
什么是文件上传 文件上传包含两部分, 一部分是选择文件,包含所有相关的界面交互。一部分是网络传输,通过一个网络请求,将文件的数据携带过去,传递到服务器中,剩下的,在服务器中如何存储…...
golang gin——文件上传(单文件,多文件)
文件上传 单文件上传 从form-data获取文件 package uploadimport ("github.com/gin-gonic/gin""net/http" ) // 单文件上传,多文件上传 func Upload(c *gin.Context) {file, _ : c.FormFile("file") // file为字段名dst : "…...
面试题:Redis和MySQL的事务区别是什么?
大家好,我是小米!今天我要和大家聊聊一个在技术面试中经常被问到的问题:“Redis和MySQL的事务区别是什么?”这个问题看似简单,但实际上涉及到了数据库和缓存两个不同领域的知识,让我们一起来深入了解一下吧…...
Canvas绘图
Canvas绘图 Canvas的意义 随着前端的不断发展,页面特效越来越炫酷,W3C组织也不断退出新的CSS特性:例如各种渐变,瀑布流布局,各种阴影,但是随着需求越来越花哨,W3C表示:我去你妈的&…...
逻辑回归评分卡
文章目录 一、基础知识点(1)逻辑回归表达式(2)sigmoid函数的导数损失函数(Cross-entropy, 交叉熵损失函数)交叉熵求导准确率计算评估指标 二、导入库和数据集导入库读取数据 三、分析与训练四、模型评价ROC曲线KS值再做特征筛选生成报告 五、行为评分卡模型表现总结 一、基础知…...
DPDK系列之三十三DPDK并行机制的底层支持
一、背景介绍 在前面介绍了DPDK中的上层对并行的支持,特别是对多核的支持。但是,大家都知道,再怎么好的设计和架构,再优秀的编码,最终都要落到硬件和固件对整个上层应用的支持。单纯的硬件好处理,一个核不…...
LVGL_基础控件滚轮roller
LVGL_基础控件滚轮roller 1、创建滚轮roller控件 /* 创建一个 lv_roller 部件(对象) */ lv_obj_t * roller lv_roller_create(lv_scr_act()); // 创建一个 lv_roller 部件(对象),他的父对象是活动屏幕对象// 将部件(对象)添加到组,如果设置了默认组,…...
王道考研操作系统——文件管理
磁盘的基础知识 .txt用记事本这个应用程序打开,文件最重要的属性就是文件名了 保护信息:操作系统对系统当中的各个用户进行了分组,不同分组的用户对文件的操作权限是不一样的 文件的逻辑结构就是文件内部的数据/记录应该被怎么组织起来&…...
商业智能系统的主要功能包括数据仓库、数据ETL、数据统计输出、分析功能
ETL服务内容包含: 数据迁移数据合并数据同步数据交换数据联邦数据仓库...
基于帝国主义竞争优化的BP神经网络(分类应用) - 附代码
基于帝国主义竞争优化的BP神经网络(分类应用) - 附代码 文章目录 基于帝国主义竞争优化的BP神经网络(分类应用) - 附代码1.鸢尾花iris数据介绍2.数据集整理3.帝国主义竞争优化BP神经网络3.1 BP神经网络参数设置3.2 帝国主义竞争算…...
将python项目部署在一台服务器上
将python项目部署在一台服务器上 1.服务器2.部署方法2.1 手动部署2.2 容器化技术部署2.3 服务器less技术部署 1.服务器 服务器一般为:物理服务器和云服务器。 我的是物理服务器:这是将服务器硬件直接放置在您自己的数据中心或机房的传统方法。这种方法需…...
【C语言】善于利用指针(二)
💗个人主页💗 ⭐个人专栏——C语言初步学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 导读:1. 字符指针1.1 字符串的引用方式1.2 有趣的面试题 2. 数组指针2.1 一维数组指针的定义2.2 一维数组…...
Python调用C++
https://www.cnblogs.com/renfanzi/p/10276997.html Linux使用Python调用C/C接口(一) - 代码先锋网 linux系统上使用Python调用C生成的.so动态链接库opencv_linux 下python 编译为so ,给c使用_比赛学习者的博客-CSDN博客 https://www.cnblogs.com/shuimuqingyang/p/13618105…...
自己实现扫描全盘文件的函数。
1.自己实现扫描全盘的函数 def scan_disk(dir): global count,dir_count if os.path.isdir(dir): files os.listdir(dir) for file in files: print(file) dir_count 1 if os.path.isdir(dir os.sep file): …...
JSON文件读写
1、依赖文件 #include <QFile> #include <QJsonDocument> #include <QJsonObject> #include <QDebug> #include <QStringList>2、头文件 bool ReadJsonFile(const QString& filePath""); bool WriteJsonFile(const QString&…...
VisualStudio2022环境下Release模式编译dll无法使用TLS函数问题
Debug x86环境下正常使用TLS回调函数 切换到Release发现程序没有使用tls 到C/C > 优化中将全程序优化关闭即可...
ChatGPT基础使用总结
文章目录 一、ChatGPT基础概念大型语言模型LLMs---一种能够以类似人类语言的方式“说话”的软件ChatGPT定义---OpenAI 研发的一款聊天机器人程序(2022年GPT-3.5,属于大型语言模型)ChatGPT4.0---OpenAI推出了GPT系列的最新模型ChatGPT典型使用…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
