当前位置: 首页 > 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年后端开发常用的案例,以高质量的代码提取出来,并对其进行了介绍。…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...