后端——AOP异步日志

需求分析

在SpringBoot系统中,一般会对访问系统的请求做日志记录的需求,确保系统的安全维护以及查看接口的调用情况,可以使用AOP对controller层的接口进行增强,作日志记录。日志保存在数据库当中,为了避免影响接口的响应,降低用户体验度,采用异步的方式记录日志,避免日志记录阻塞接口请求

实现原理

通过定义AOP切面,访问接口之前,使用前置通知记录一些有用的数据,如ip地址、请求方式、操作人等等,接口执行完之后使用后置通知记录本次请求执行的实践、执行结果等等信息。
在这里插入图片描述

实现代码

AOP日志切面

定义切点表达式指向Controller的所有方法,即指向所有接口

/*** @Description 日志切面类*/
@Aspect
@Component
public class SysLogAspect {@AutowiredSysLogDao sysLogDao;/*** 开始时间*/private Long startTime;/*** ip*/private String ip;/*** 请求接口名*/private String interfaceName;/*** 请求方式*/private String methodWays;/*** 请求方法路径*/private String requestMethodUrl;/*** 请求类方法参数*/private String requestArgs;//声明切点@Pointcut("execution(public * com.*.*.controller.*.*(..)) || execution(public * com.*.controller.*.*(..))"private void aspect() {}@Before("aspect()")public void before(JoinPoint joinPoint) throws NoSuchMethodException {//开始访问的时间startTime = System.currentTimeMillis();ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();//获取请求ipip = request.getRemoteAddr();//获取请求方法名interfaceName = request.getRequestURI();//获取请求方式methodWays = request.getMethod();//获取请求方法地址requestMethodUrl = joinPoint.getSignature().toString();//获取请求参数requestArgs = Arrays.toString(joinPoint.getArgs());}@AfterReturning(pointcut = "aspect()")public void methodAfterReturning() {Long endTime = System.currentTimeMillis();//执行时长Double time = (endTime - startTime) / 1000.0;SysLog sysLog = new SysLog();//获取当前用户Subject currentUser = SecurityUtils.getSubject();UserLoginInfo subject = (UserLoginInfo) currentUser.getPrincipal();if (!ObjectUtils.isEmpty(subject)) {//用户名sysLog.setUserName(subject.getUserName());}//用户操作switch (methodWays) {case "GET":sysLog.setOperation(BusinessType.SELECT.getValue());break;case "POST":sysLog.setOperation(BusinessType.INSERT.getValue());break;case "PUT":sysLog.setOperation(BusinessType.UPDATE.getValue());break;case "DELETE":sysLog.setOperation(BusinessType.DELETE.getValue());break;}//请求IPsysLog.setIp(ip);//请求类方法参数sysLog.setParams(requestArgs);//执行时长sysLog.setTime(time.toString());//请求方法路径sysLog.setMethod(requestMethodUrl);//入库时间String createTime = DateTimeUtils.getNowDateTime();sysLog.setCreateTime(createTime);//获取系统接口路径信息列表List<ApiInfo> apiInfos = sysLogDao.selectApiInfos();for (ApiInfo apiInfo : apiInfos) {//调用接口路径与接口信息列表进行匹配if (apiInfo.getApiName().equals(interfaceName)) {//菜单模块sysLog.setMenuModel(apiInfo.getMenuOperation());break;}}//异步新增日志AsyncManager.me().execute(AsyncFactory.recordOper(sysLog));}
}

异步任务管理器(线程池)

定义一个单例的异步任务管理器,使用线程池完成异步操作

/*** @description: 异步任务管理器**/
public class AsyncManager {/*** 操作延迟10毫秒*/private final int OPERATE_DELAY_TIME = 10;/*** 异步操作任务调度线程池*/private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");/*** 单例模式*/private AsyncManager(){}private static AsyncManager me = new AsyncManager();public static AsyncManager me(){return me;}/*** 执行任务** @param task 任务*/public void execute(TimerTask task){executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);}/*** 停止任务线程池*/public void shutdown(){ThreadsUtil.shutdownAndAwaitTermination(executor);}
}

异步工厂

这里定义异步工厂去创建日记记录的任务,同时也方便系统扩展其他的异步操作

public class AsyncFactory {/*** 操作日志记录** @param operLog 操作日志信息* @return 任务task*/public static TimerTask recordOper(final SysLog operLog) {return new TimerTask() {@Overridepublic void run() {// 远程查询操作地点SpringUtils.getBean(SysLogService.class).addSysLogInfo(operLog);}};}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75836.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flink广播算子Broadcast

文章目录 一、Broadcast二、代码示例三.或者第二种(只读取一个csv文件到广播内存中)提示:以下是本篇文章正文内容,下面案例可供参考 一、Broadcast 为了关联一个非广播流(keyed 或者 non-keyed)与一个广播流(BroadcastStream),我们可以调用非广播流的方法 connect(),…

Redis 和 MySQL双写一致性的更新策略有哪些?常见面试题深度解答。

目录 一. 业务数据查询&#xff0c;更新顺序简要分析 二. 更新数据库、查询数据库、更新缓存、查询缓存耗时对比 2.1 更新数据库&#xff08;最慢&#xff09; 2.2 查询数据库&#xff08;较慢&#xff09; 2.3 更新缓存&#xff08;次快&#xff09; 2.4 查询缓存&#…

SRT协议

SRT&#xff08;Secure Reliable Transport&#xff09;是一种开源的视频传输协议&#xff0c;专为高丢包、高延迟网络环境设计&#xff0c;结合了UDP的低延迟和TCP的可靠性&#xff0c;广泛应用于直播、远程制作、视频会议等场景。 定位&#xff1a;SRT协议的官方C/C实现库&am…

“征服HTML引号恶魔:“完全解析手册”!!!(quot;表示双引号)

&#x1f6a8;&#x1f4e2; "征服HTML引号恶魔&#xff1a;“完全解析手册” &#x1f4e2;&#x1f6a8; &#x1f3af; 博客引言&#xff1a;当引号变成"恶魔" &#x1f631; 是否遇到过这种情况&#xff1a; 写HTML时满心欢喜输入<div title"他…

npm install 卡在创建项目:sill idealTree buildDeps

参考&#xff1a; https://blog.csdn.net/PengXing_Huang/article/details/136460133 或者再执行 npm install -g cnpm --registryhttps://registry.npm.taobao.org 或者换梯子

c++中cpp文件从编译到执行的过程

C 文件从编写到执行的过程可以分为几个主要阶段&#xff1a;编写代码、预处理、编译、汇编、链接和运行。以下是每个阶段的详细说明&#xff1a; 1. 编写代码 这是整个过程的起点。程序员使用文本编辑器&#xff08;如 VSCode、Sublime Text 或其他 IDE&#xff09;编写 C 源…

PROE 与 STL 格式转换:开启 3D 打印及多元应用的大门

在 3D 设计与制造的复杂生态中&#xff0c;将 PROE 格式转换为 STL 格式绝非无端之举&#xff0c;而是有着深厚且多元的现实需求作为支撑。 一、文件格式介绍​ &#xff08;一&#xff09;PROE 格式​ PROE 作为一款参数化设计软件&#xff0c;采用基于特征的参数化建模技术…

开发中后端返回下划线数据,要不要统一转驼峰?

先说结论。看情况&#xff01;&#xff01;&#xff01;&#xff01; 前端 主要用 JS/TS 建议后端返回 camelCase&#xff0c;减少前端转换成本。后端 主要是 Python/Go 建议保持 snake_case&#xff0c;前端做转换。但是团队统一风格最重要&#xff01;如果统一返回驼峰就驼峰…

docker pull时报错:https://registry-1.docker.io/v2/

原文&#xff1a;https://www.cnblogs.com/sdgtxuyong/p/18647915 https://www.cnblogs.com/OneSeting/p/18532166 docker 换源&#xff0c;解决连接不上的问题。 编辑以下文件&#xff0c;不存在则创建&#xff1a; vim /etc/docker/daemon.json {"registry-mirrors&qu…

Pytorch学习笔记(十二)Learning PyTorch - NLP from Scratch

这篇博客瞄准的是 pytorch 官方教程中 Learning PyTorch 章节的 NLP from Scratch 部分。 官网链接&#xff1a;https://pytorch.org/tutorials/intermediate/nlp_from_scratch_index.html 完整网盘链接: https://pan.baidu.com/s/1L9PVZ-KRDGVER-AJnXOvlQ?pwdaa2m 提取码: …

基础算法02——冒泡排序(Bubble Sort)

冒泡排序&#xff08;Bubble Sort&#xff09; 冒泡排序&#xff1a;是一种简单的排序算法&#xff0c;其基本思想是通过重复遍历要排序的列表&#xff0c;比较相邻的元素&#xff0c;并在必要时&#xff08;即前面的数比后面的数大的时候&#xff09;交换它们的位置&#xff…

RestTemplate远程调用接口方式

1.Post(body空参) 也就是说需要给一个空的json 代码: String getDeviceUrl this.MOVABLE_URL "detected-data/getMachineLists"; // 远程调用 RestTemplate restTemplate new RestTemplate(); restTemplate.getMessageConverters().set(1,new StringHttpMessageC…

ar头显和眼镜图像特效处理

使用一个线程从摄像头或者其他设备循环读取图像数据写入链表&#xff0c;另一个线程从链表循环读取数据并做相应的特效处理&#xff0c;由于写入的速度比读取的快&#xff0c;最终必然会因为写入过快导致线程读写一帧而引发冲突和数据帧正常数据帧被覆盖。最好使用共享内存&…

mysql--socket报错

错误原因分析 MySQL 服务未运行&#xff08;最常见原因&#xff09; 错误中的 (2) 表示 “No such file or directory”&#xff0c;即 /tmp/mysql.sock 不存在这通常意味着 MySQL 服务器根本没有启动 socket 文件路径不匹配 客户端尝试连接 /tmp/mysql.sock但 MySQL 服务器可…

labview加载matlab数据时报错提示:对象引用句柄无效。

1. labview报错提示 labview加载mat数据时报错提示&#xff1a;对象引用句柄无效。返回该引用句柄的节点可能遇到错误&#xff0c;并没有返回有效的引用句柄。该引用句柄所指的存储可能在执行调用之前已关闭。报错提示如下&#xff1a; 这是由于labview缺少matlab MathWorks导…

面试计算机操作系统解析(一中)

判断 1. 一般来说&#xff0c;先进先出页面置换算法比最近最少使用页面置换算法有较少的缺页率。&#xff08;✘&#xff09; 正确答案&#xff1a;错误解释&#xff1a;FIFO&#xff08;先进先出&#xff09;页面置换算法可能导致“Belady异常”&#xff0c;即页面数增加反而…

如何防御TCP洪泛攻击

TCP洪泛攻击&#xff08;TCP Flood Attack&#xff09;是一种常见的分布式拒绝服务&#xff08;DDoS&#xff09;攻击手段&#xff0c;以下是其原理、攻击方式和危害的详细介绍&#xff1a; 定义与原理 TCP洪泛攻击利用了TCP协议的三次握手过程。在正常的TCP连接建立过程中&a…

20250330 Pyflink with Paimon

1. 数据湖 2. 本地安装Pyflink和Paimon 必须安装Python 3.11 Pip install python -m pip install apache-flink1.20.1 需要手动加入这两个jar 测试代码&#xff1a; import argparse import logging import sys import timefrom pyflink.common import Row from pyflink.tab…

-PHP 应用SQL 盲注布尔回显延时判断报错处理增删改查方式

#PHP-MYSQL-SQL 操作 - 增删改查 1 、功能&#xff1a;数据查询(对数据感兴趣&#xff09; 查询&#xff1a; SELECT * FROM news where id$id 2 、功能&#xff1a;新增用户&#xff0c;添加新闻等&#xff08;对操作的结果感兴趣&#xff09; 增加&#xff1a; INSERT INT…

【学习记录】大模型微调之使用 LLaMA-Factory 微调 Qwen系列大模型,可以用自己的数据训练

一、LoRA微调的基本原理 1、基本概念 LoRA&#xff08;Low-Rank Adaptation&#xff09;是一种用于大模型微调的技术&#xff0c;通过引入低秩矩阵来减少微调时的参数量。在预训练的模型中&#xff0c;LoRA通过添加两个小矩阵B和A来近似原始的大矩阵ΔW&#xff0c;从而减少需…