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

Spring Boot @Aspect 切面编程实现访问请求日志记录

aop切面编程想必大家都不陌生了,aspect可以很方便开发人员对请求指定拦截层,一般是根据条件切入到controller控制层,做一些鉴权、分析注解、获取类名方法名参数、记录操作日志等。

在SpringBoot中使用aop首先是要导入依赖如下:

<!-- 切面编程 @Aspect、@Pointcut等依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后基本使用如下:


@Aspect
@Component
@Order(1)
public class WebLogAspect {private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);@Pointcut("execution(public * flutter.dio.model.controller.*.*(..))")public void webLog() {}@Before("webLog()")public void doBefore(JoinPoint joinPoint) throws Throwable {}@AfterReturning(value = "webLog()", returning = "ret")public void doAfterReturning(Object ret) throws Throwable {}/*** 环绕通知** @param joinPoint* @return* @throws Throwable*/@Around("webLog()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {... ...return result;}}

@Pointcut 定义切入点标记注解,比如我这里是指定路径下的controller
在这里插入图片描述
其他注解描述

  • @Before:前置增强,在某个JoinPoint执行前的增强

  • @After:final增强,不管抛异常还是正常退出都执行的增强

  • @AfterReturning:后置增强,方法正常退出时执行

  • @AfterThrowing:异常抛出增强,抛出异常后执行

  • @Around:环绕增强,包围一个连接点的增强,最强大的一个方式,且常用

  • ProceedingJoinPoint 和 JoinPoint 是 Spring 中 AOP 框架中两个常用的接口,它们的主要区别在于使用场景不同。

  • JoinPoint 是 Spring AOP 中最常用的接口,它表示在程序执行过程中明确的点。这个接口提供了许多方法,可以访问到当前被拦截方法的信息。

  • ProceedingJoinPoint 是一个特殊的 JoinPoint,它表示可以继续进行被拦截方法的执行。它提供了一个 proceed() 方法,可以执行被拦截的方法。这个接口只能在 @Around 注解修饰的方法中使用。

所以我在 doAround 方法中记录日志信息:

//记录请求开始时间long startTime = System.currentTimeMillis();//获取当前请求对象ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();//记录请求信息(通过Logstash传入Elasticsearch)WebLog webLog = new WebLog();Object result = joinPoint.proceed();Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;//获取当前请求方法Method method = methodSignature.getMethod();if (method.isAnnotationPresent(ApiOperation.class)) {ApiOperation log = method.getAnnotation(ApiOperation.class);webLog.setDescription(log.value());}long endTime = System.currentTimeMillis();String urlStr = request.getRequestURL().toString();webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));//请求IPwebLog.setIp(request.getRemoteUser());//请求方法webLog.setMethod(request.getMethod());//请求参数webLog.setParameter(getParameter(method, joinPoint.getArgs()));//请求结果webLog.setResult(result);//请求时间webLog.setStartTime(startTime);webLog.setSpendTime((int) (endTime - startTime));//请求地址webLog.setUri(request.getRequestURI());webLog.setUrl(request.getRequestURL().toString());LOGGER.info("{}", JSONUtil.parse(webLog));

getParameter 方法主要用来实现获取请求参数,代码如下:

/*** 根据方法和传入的参数获取请求参数*/
private Object getParameter(Method method, Object[] args) {List<Object> argList = new ArrayList<>();Parameter[] parameters = method.getParameters();for (int i = 0; i < parameters.length; i++) {//将RequestBody注解修饰的参数作为请求参数RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);if (requestBody != null) {argList.add(args[i]);}//将RequestParam注解修饰的参数作为请求参数RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);if (requestParam != null) {Map<String, Object> map = new HashMap<>();String key = parameters[i].getName();if (!ObjectUtils.isEmpty(requestParam.value())) {key = requestParam.value();}map.put(key, args[i]);argList.add(map);}}if (argList.size() == 0) {return null;} else if (argList.size() == 1) {return argList.get(0);} else {return argList;}
}

执行一个请求,控制台输入日志如下:
在这里插入图片描述
我在这里把日志封装入了 WebLog 自定义类中,大家可以根据实际情况来对日志进行保存处理

import lombok.Data;
@Data
public class WebLog {/*** 操作描述*/private String description;/*** 操作用户*/private String username;/*** 操作时间*/private Long startTime;/*** 消耗时间*/private Integer spendTime;/*** 根路径*/private String basePath;/*** URI*/private String uri;/*** URL*/private String url;/*** 请求类型*/private String method;/*** IP地址*/private String ip;private Object parameter;private Object result;
}

相关文章:

Spring Boot @Aspect 切面编程实现访问请求日志记录

aop切面编程想必大家都不陌生了&#xff0c;aspect可以很方便开发人员对请求指定拦截层&#xff0c;一般是根据条件切入到controller控制层&#xff0c;做一些鉴权、分析注解、获取类名方法名参数、记录操作日志等。 在SpringBoot中使用aop首先是要导入依赖如下&#xff1a; …...

初学者的第一个Linux驱动

软件环境&#xff1a;Ubuntu20.04 Linux内核源码&#xff1a;3.4.39 硬件环境&#xff1a;GEC6818 什么是驱动&#xff1f;简单来说就是让硬件工作起来的程序代码。 Linux驱动模块加载有两种方式&#xff1a; 1、把写好的驱动代码直接编译进内核。 2、把写好的驱动代码编…...

7. 拼数

1 题目描述 拼数成绩10开启时间2021年09月24日 星期五 18:00折扣0.8折扣时间2021年11月15日 星期一 00:00允许迟交否关闭时间2021年11月23日 星期二 00:00 设有 n个正整数 a[1]​…a[n]​&#xff0c;将它们联接成一排&#xff0c;相邻数字首尾相接&#xff0c;组成一个最大的整…...

Java每天15道面试题 | Redis

redis 和 和 memcached 什么区别&#xff1f;为什么高并发下有时单线程的 redis 比多线程的memcached 效率要高&#xff1f; 区别&#xff1a; 1.mc 可缓存图片和视频。rd 支持除 k/v 更多的数据结构; 2.rd 可以使用虚拟内存&#xff0c;rd 可持久化和 aof 灾难恢复&#xff0…...

13_pinctrl子系统

总结 pinctrl作为驱动 iomuxc节点在设备树里面 存储全部所需的引脚配置信息 iomux节点匹配pinctrl子系统 控制硬件外设的时候 要知道有哪些gpio 再看gpio有哪些服用寄存器 接着在程序配置gpio相关寄存器 这样搞效率很低 所以用iomux节点保存所有的引脚组 pinctrl驱动起来的时…...

Linux系统对于实施人员的价值

Linux系统对于实施人员的价值 随着互联网的发展&#xff0c;linux系统越来越突显了巨大的作用&#xff0c;很多互联网公司&#xff0c;政府企业&#xff0c;只要用到服务器的地方几乎都能看到linux系统的身影&#xff0c;可以说服务是不是在linux系统跑的代表了企业的技术水平&…...

ForkJoin 和 Stream并行流

还在用 for 循环计算两个数之间所有数的和吗&#xff1f;下面提供两种新方法&#xff01; 1. ForkJoin 1.1 背景 要知道&#xff0c;在一个方法中&#xff0c;如果没有做特殊的处理&#xff0c;那么在方法开始到结束使用的都是同一个线程&#xff0c;无论你的业务有多复杂 那…...

逻辑优化-cofactor

1. 简介 逻辑综合中的Cofactor优化方法是一种重要的逻辑优化技术。它通过提取逻辑电路中的共同部分&#xff0c;从而简化电路、减小面积和延迟。该方法广泛应用于电子设计自动化&#xff08;EDA&#xff09;领域中的逻辑综合、等价转换和优化等方面。 Cofactor优化方法最早由…...

车道线检测CondLaneNet论文和源码解读

CondLaneNet: a Top-to-down Lane Detection Framework Based on Conditional Convolution Paper&#xff1a;https://arxiv.org/pdf/2105.05003.pdf code&#xff1a;GitHub - aliyun/conditional-lane-detection 论文解读&#xff1a; 一、摘要 这项工作作为车道线检测任…...

vue3的插槽slots

文章目录普通插槽Test.vueFancyButton.vue具名插槽Test.vueBaseLayout.vue作用域插槽默认插槽Test.vueBaseLayout.vue具名作用域插槽Test.vueBaseLayout.vue普通插槽 父组件使用子组件时&#xff0c;在子组件闭合标签中提供内容模板&#xff0c;插入到子组件定义的出口的地方 …...

docker学校服务器管理

docker 学校服务器管理使用docker&#xff0c;docker使用go语言编写。对于docker的理解&#xff0c;需要知道几个关键字docker, scp&#xff0c;images, container。 docker-码头工人scp-传输命令images/repository-镜像container-容器 docker是码头工人&#xff0c;scp相当…...

pv和pvc

一、PV和PVC详解当前&#xff0c;存储的方式和种类有很多&#xff0c;并且各种存储的参数也需要非常专业的技术人员才能够了解。在Kubernetes集群中&#xff0c;放了方便我们的使用和管理&#xff0c;Kubernetes提出了PV和PVC的概念&#xff0c;这样Kubernetes集群的管理人员就…...

k8s篇之Pod 干预与 PDB

文章目录自愿干预和非自愿干预PDBPDB 示例分离集群所有者和应用程序所有者角色如何在集群上执行中断操作自愿干预和非自愿干预 Pod 不会消失&#xff0c;除非有人&#xff08;用户或控制器&#xff09;将其销毁&#xff0c;或者出现了不可避免的硬件或软件系统错误。 我们把这…...

Django学习17 -- ManytoManyField

1. ManyToManyField &#xff08;参考&#xff1a;Django Documentation Release 4.1.4&#xff09; 类定义 class ManyToManyField(to, **options)使用说明 A many-to-many relationship. Requires a positional argument: the class to which the model is related, which w…...

既然有MySQL了,为什么还要有Redis?

目录专栏导读一、同样是缓存&#xff0c;用map不行吗&#xff1f;二、Redis为什么是单线程的&#xff1f;三、Redis真的是单线程的吗&#xff1f;四、Redis优缺点1、优点2、缺点五、Redis常见业务场景六、Redis常见数据类型1、String2、List3、Hash4、Set5、Zset6、BitMap7、Bi…...

RSTP基础要点(上)

RSTP基础RSTP引入背景STP所存在的问题RSTP对于STP的改进端口角色重新划分端口状态重新划分快速收敛机制&#xff1a;PA机制端口快速切换边缘端口的引入RSTP引入背景 STP协议虽然能够解决环路问题&#xff0c;但是由于网络拓扑收敛较慢&#xff0c;影响了用户通信质量&#xff…...

Linux操作系统学习(信号处理)

文章目录进程信号信号的产生方式&#xff08;信号产生前&#xff09;1. 硬件产生2.调用系统函数向进程发信号3.软件产生4.定位进程崩溃的代码&#xff08;进程异常退出产生信号&#xff09;信号保存的方式&#xff08;信号产生中&#xff09;获取pending表&&修改block表…...

CopyOnWriteArrayList 源码解读

一、CopyOnWriteArrayList 源码解读 在 JUC 中&#xff0c;对于 ArrayList 的线程安全用法&#xff0c;比较推崇于使用 CopyOnWriteArrayList &#xff0c;那 CopyOnWriteArrayList是怎么解决线程安全问题的呢&#xff0c;本文带领大家一起解读下 CopyOnWriteArrayList 的源码…...

方法

方法方法&#xff08;函数&#xff09;一、课前问答二、方法和函数三、方法的参数3.1 单个参数3.2 多个参数四、方法的返回值五、方法的多级调用六、递归方法&#xff08;函数&#xff09; 一、课前问答 1、break和continue的区别 2、嵌套循环的执行流程 3、二进制有哪些运算&…...

C/C++实现发送邮件功能(附源码)

C++常用功能源码系列 本文是C/C++常用功能代码封装专栏的导航贴。部分来源于实战项目中的部分功能提炼,希望能够达到你在自己的项目中拿来就用的效果,这样更好的服务于工作实践。 专栏介绍:专栏讲本人近10年后端开发常用的案例,以高质量的代码提取出来,并对其进行了介绍。…...

【2026 实测】10 分钟配好 OpenClaw 中转站:GPT、Claude、Gemini、DeepSeek 一键切换(小白可跟做)

你是不是也遇到过这些问题&#xff1a; 官方 API 偶发不稳定&#xff0c;任务跑到一半中断想切换模型时&#xff0c;要反复改配置、改 Key明明照着文档配了&#xff0c;结果还是 400/401 报错 如果你正在本地用 OpenClaw 做 AI 编程或多模型对比&#xff0c;这篇就是给你的。…...

如何用思源宋体CN打造专业级中文字体解决方案?开源字体的技术优势与实战指南

如何用思源宋体CN打造专业级中文字体解决方案&#xff1f;开源字体的技术优势与实战指南 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 在数字化内容创作中&#xff0c;中文字体的选择…...

SEO_如何制定有效的SEO策略?分步指南(132 )

如何制定有效的SEO策略&#xff1f;分步指南 在互联网时代&#xff0c;一个网站的成功往往取决于其在搜索引擎上的排名。制定有效的SEO策略是提升网站流量、吸引潜在客户的关键。本文将为你提供一份详细的分步指南&#xff0c;帮助你制定并实施有效的SEO策略。 第一步&#x…...

Youtu-VL-4B-Instruct问题解决:服务启动失败?常见错误排查与修复

Youtu-VL-4B-Instruct问题解决&#xff1a;服务启动失败&#xff1f;常见错误排查与修复 1. 服务启动失败的常见表现 当你尝试启动Youtu-VL-4B-Instruct服务时&#xff0c;可能会遇到以下几种典型问题&#xff1a; 1.1 端口冲突错误 最常见的错误是端口已被占用&#xff0c…...

NCM格式转换技术解析:从加密限制到音频自由的技术实现

NCM格式转换技术解析&#xff1a;从加密限制到音频自由的技术实现 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 一、问题场景&#xff1a;数字音乐的格式枷锁与用户困境 1.1 音乐人的设备兼容困境 独立音乐人小林最近遇到了一个…...

openclaw v2026.4.1 发布!16 大核心功能升级 + 28 项关键修复,AI 智能体网关全面进化,稳定性与安全性再攀高峰

一、前言&#xff1a;开源AI智能体标杆再升级&#xff0c;v2026.4.1引领本地自动化新潮流 2026年4月2日&#xff0c;开源AI智能体执行网关领域的标杆项目OpenClaw正式推出v2026.4.1最新版本。作为一款主打本地优先、自托管、全开源的AI智能体框架&#xff0c;OpenClaw自诞生以来…...

Qwen3.5-9B-AWQ-4bit效果展示:高清截图OCR、场景描述、主体识别实测集

Qwen3.5-9B-AWQ-4bit效果展示&#xff1a;高清截图OCR、场景描述、主体识别实测集 1. 模型能力概览 Qwen3.5-9B-AWQ-4bit是一款基于量化技术的多模态视觉理解模型&#xff0c;能够同时处理图像和文本输入&#xff0c;输出高质量的中文分析结果。这个4bit量化版本在保持核心能…...

华为eNSP实战:手把手教你用单臂路由打通不同VLAN,附排错命令清单

华为eNSP单臂路由实战&#xff1a;跨VLAN通信配置与深度排错指南 当企业网络规模扩大时&#xff0c;VLAN隔离是保障安全性和广播域控制的必要手段。但实际业务中&#xff0c;不同部门间的数据交互需求常常需要跨越VLAN边界。在华为认证体系HCIA和HCIP的实验环境中&#xff0c;单…...

C++ 异常安全与 RAII 模式结合

C异常安全与RAII模式结合&#xff1a;构建健壮资源管理体系 在C开发中&#xff0c;异常处理与资源管理是保证程序健壮性的核心挑战。传统的手动资源释放容易因异常抛出导致泄漏&#xff0c;而RAII&#xff08;资源获取即初始化&#xff09;模式通过对象生命周期自动化管理资源…...

SeqGPT-560M入门指南:Web界面操作+Jupyter调试+API调用三路径并行

SeqGPT-560M入门指南&#xff1a;Web界面操作Jupyter调试API调用三路径并行 1. 从零开始&#xff1a;认识SeqGPT-560M 如果你正在寻找一个开箱即用、能快速处理中文文本分类和信息抽取的AI工具&#xff0c;那么SeqGPT-560M绝对值得你花十分钟了解一下。 简单来说&#xff0c…...