使用springboot aop记录接口请求的参数及响应

概述

使用aop做日志记录,记录输入的参数名及参数值,并且记录接口响应结果。

切面类

package com.zou.metabox.common.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;/*** @author BIGSHU0923* @description com.zou.metabox 中Controller层的的日志切面* @since 7/30/2023  5:32 PM*/
@Aspect
@Component
@Slf4j
public class LoggingAspect {/*** com.zou.metabox.controller 包中公共方法的切入点*/@Pointcut("execution(public * com.zou.metabox.controller.*.*(..))")public void loggingPointcut(){// 暂不用处理}/**在日志切入点之前执行的通知。记录方法名称和请求参数。@param joinPoint 控制器类中的连接点*/@Before("loggingPointcut()")public void logBefore(JoinPoint joinPoint){Object[] args = joinPoint.getArgs();MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();String[] parameterNames = methodSignature.getParameterNames();Map<String, Object> requestMap = new HashMap<>();IntStream.range(0, parameterNames.length).forEach(i -> requestMap.put(parameterNames[i], args[i]));log.info("Before method:{}|{}", joinPoint.getSignature().getName(), requestMap);}/**在日志切入点之后和方法成功执行后执行的通知。记录方法名称和返回结果。@param joinPoint 控制器类中的连接点@param result 方法的返回结果*/@AfterReturning(pointcut = "execution(public * com.zou.metabox.controller.*.*(..))", returning = "result")public void logResponse(JoinPoint joinPoint, Object result){log.info("Method response:{}|{}", joinPoint.getSignature().getName(), result.toString());}}

注意

这个切面定义的切点是在@Pointcut这个注解中定义的。我这里定义的是Controller中所有的public方法。

@After和@Afterreturning的区别

@After和@AfterReturning是两个不同的切面通知类型。

@After通知会在目标方法执行之后触发,无论目标方法是否抛出异常。所以在@After通知中不能访问目标方法的返回值。

@AfterReturning通知只在目标方法成功执行并返回后触发,可以访问目标方法的返回值。一般使用@AfterReturning通知来收集方法的执行结果或进行日志记录。

优化

@Around注解可以更方便地控制代理链条的行为,具体是指通过@Around注解实现的方法既可以代替@Before和@AfterReturning注解,也可以控制何时进入、何时退出被代理的方法。在执行目标方法之前,可以在@Around注解标注的方法中编写一些逻辑来决定是否继续执行目标方法,还可以修改传递给目标方法的参数。在执行完目标方法后,可以在@Around注解标注的方法中对返回值进行处理或者抛出异常。
@Around可以控制何时进入、何时退出被代理的方法。具体是通过ProceedingJoinPoint参数调用proceed()方法来执行目标方法。如下面的result = pjp.proceed();这里起始执行的就是接口的方法。所以可以控制何时进入、何时退出被代理的方法。

    @Around("loggingPointcut()")public Object around(ProceedingJoinPoint pjp) throws Throwable{// 获取类名String className = pjp.getTarget().getClass().getTypeName();// 获取方法名String methodName = pjp.getSignature().getName();// 获取参数名String[] parameterNames = ((MethodSignature) pjp.getSignature()).getParameterNames();Object result = null;// 获取参数值Object[] args = pjp.getArgs();// 获取请求HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();// 获取请求的urlString url = request.getRequestURL().toString();// 请求参数,以参数名和值为键值对Map<String, Object> paramMap = new HashMap<>();IntStream.range(0, parameterNames.length).forEach(i->paramMap.put(parameterNames[i], args[i]));// header参数Enumeration<String> headerNames = request.getHeaderNames();Map<String, Object> headerMap = new HashMap<>();while (headerNames.hasMoreElements()){String headerName = headerNames.nextElement();String headerValue = request.getHeader(headerName);headerMap.put(headerName, headerValue);}// 打印请求参数,记录起始时间long start = System.currentTimeMillis();log.info("请求| 请求接口:{} | 类名:{} | 方法:{} | header参数:{} | 参数:{} | 请求时间:{}", url, className, methodName, headerMap, paramMap, LocalDateTime.now());try {result = pjp.proceed();} catch (Exception e) {log.error("返回| 处理时间:{} 毫秒 | 返回结果 :{}", (System.currentTimeMillis() - start), "failed");throw e;}// 获取执行完的时间 打印返回报文log.info("返回| 处理时间:{} 毫秒 | 返回结果 :{}", (System.currentTimeMillis() - start), "success");return result;}

总结

Spring AOP 是基于代理的 AOP 框架,提供了几个不同的切面建言(advice)注解:@Before、@AfterReturning、@Around、@AfterThrowing 和 @After。这些注解分别表示在目标方法执行的不同时间点进行增强处理。

具体来说:

@Before:表示在目标方法执行前进行增强处理。
@AfterReturning:表示在目标方法执行后,返回结果之后进行增强处理,可以访问到方法的返回值。
@Around:表示在目标方法执行前、执行中和执行后都可以进行增强处理,并且需要手动控制何时进入、何时退出被代理的方法。
@AfterThrowing:表示在目标方法抛出异常后进行增强处理。
@After:表示在目标方法执行后,无论是否发生异常,都进行增强处理。相较于@AfterReturning,@After增强处理无法获取到方法的返回值。
在实际使用时,@Before 和 @AfterReturning 主要用于记录日志、记性权限控制等与目标方法无关的操作;@Around 则比较常用,因为它可以在目标方法的执行前后进行增强处理,并且可以更方便地控制代理链条的行为;@AfterThrowing 和 @After 通常用于回收资源,如关闭数据库连接等操作。

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

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

相关文章

【RabbitMQ】之消息的可靠性方案

目录 一、数据丢失场景二、数据可靠性方案 1、生产者丢失消息解决方案2、MQ 队列丢失消息解决方案3、消费者丢失消息解决方案 一、数据丢失场景 MQ 消息数据完整的链路为&#xff1a;从 Producer 发送消息到 RabbitMQ 服务器中&#xff0c;再由 Broker 服务的 Exchange 根据…

深度学习实践——卷积神经网络实践:裂缝识别

深度学习实践——卷积神经网络实践&#xff1a;裂缝识别 系列实验 深度学习实践——卷积神经网络实践&#xff1a;裂缝识别 深度学习实践——循环神经网络实践 深度学习实践——模型部署优化实践 深度学习实践——模型推理优化练习 深度学习实践——卷积神经网络实践&#xff…

简单认识NoSQL的Redis配置与优化

文章目录 一、关系型数据库与非关系型数据库1、关系型数据库&#xff1a;2、非关系型数据库3、关系型数据库和非关系型数据库区别&#xff1a;4、非关系型数据库应用场景 二.Redis1、简介2、优点&#xff1a;3、Redis为什么这么快&#xff1f; 三、Redis 安装部署1、安装配置2、…

解析RocketMQ:高性能分布式消息队列的原理与应用

解析RocketMQ&#xff1a;高性能分布式消息队列的原理与应用 引言 什么是消息队列 消息队列是一种消息传递机制&#xff0c;用于在应用程序和系统之间传递消息&#xff0c;实现解耦和异步通信。它通过将消息发送到一个中间代理&#xff08;消息队列&#xff09;&#xff0c;…

算法通关村第二关——链表加法的问题解析

题目类型 链表反转、栈 题目描述 * 题目&#xff1a; * 给你两个非空链表来表示两个非负整数&#xff0c;数字最高位位于链表的开始位置。 * 它们的每个节点都只存储一个数字。将这两个数相加会返回一个新的链表。 * 你可以假设除了数字0外&#xff0c;这两个数字都不会以0开头…

Centos部署Springboot项目详解

准备启动jar包&#xff0c;app.jar放入指定目录。 一、命令启动 1、启动命令 java -jar app.jar 2、后台运行 nohup java -jar app.jar >/dev/null 2>&1 & 加入配置参数命令 nohup java -Xms512M -Xmx512M -jar app.jar --server.port9080 spring.profiles…

playwright自动化项目搭建

具备功能 关键技术&#xff1a; pylaywright测试库pytest单元测试框架pytest-playwright插件 非关键技术&#xff1a; pytest-html插件pytest-rerunfailures插件seldom 测试框架 实现功能&#xff1a; 元素定位与操作分离失败自动截图并保存到HTML报告失败重跑可配置不同…

常见的排序算法

常见的排序算法 常见的排序算法包括&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;&#xff1a;依次比较相邻的元素&#xff0c;将较大的元素交换到右侧&#xff0c;逐步将最大元素移动到末尾。插入排序&#xff08;Insertion Sort&#xff09;&#xff1a;将数组…

同一数据集(相同路径)的 FID 为负数

公众号&#xff1a;EDPJ 先说结论&#xff1a;这是算法中对复数取实部的结果&#xff0c;对 FID 的影响不大。 FID是从原始图像的计算机视觉特征的统计方面&#xff0c;来衡量两组图像的相似度&#xff0c;是计算真实图像和生成图像的特征向量之间距离的一种度量。 这种视觉特…

7.事件类型

7.1鼠标事件 案例-轮播图点击切换 需求&#xff1a;当点击左右的按钮&#xff0c;可以切换轮播图 分析: ①右侧按钮点击&#xff0c;变量&#xff0c;如果大于等于8&#xff0c;则复原0 ②左侧按钮点击&#xff0c;变量–&#xff0c;如果小于0&#xff0c;则复原最后一张 ③鼠…

Service onUnbind学习

Service 的onUnbind在所有的连接断开后才执行&#xff0c;就是这么设计的&#xff0c;所有连接断开后才通知service&#xff0c;为destory作准备。 查看Service onUnbind的定义 543 /** 544 * Called when all clients have disconnected from a particular interface…

详解主流的Hybrid App 技术框架与研发方案

移动操作系统在经历了诸神混战之后&#xff0c;BlackBerry OS、Symbian OS、Windows Phone等早期的移动操作系统逐渐因失去竞争力而退出。目前&#xff0c;市场上主要只剩下安卓和iOS两大阵营&#xff0c;使得iOS和安卓工程师成为抢手资源。然而&#xff0c;由于两者系统的差异…

idea集成jrebel实现热部署

文章目录 idea集成jrebel实现热部署下载jrebel 插件包下载jrebel mybatisplus extensition 插件包基础配置信息情况一其次情况三情况四情况五情况六情况七 验证生效与否 Jrebel热部署不生效的解决办法 idea集成jrebel实现热部署 在平常开发项目中&#xff0c;我们通常是修改完…

Mongodb SQL 到聚合映射快速参考

SQL 映射 聚合管道允许MongoDB 提供原生聚合功能&#xff0c;对应于 SQL 中许多常见的数据聚合操作。比如&#xff1a;GROUP BY、COUNT()、UNION ALL 测试数据 For MySQL rootlocalhost 14:40:40 [test]> select * from orders; -------------------------------------…

java基本类型和String类型的相互转化

文章目录 java基本类型和String类型的相互转化String 类型转基本类型byteshortintlongdoublefloat 基本类型转String类型方法1方法2 java基本类型和String类型的相互转化 String 类型转基本类型 byte String s "123"; byte b Byte.parseByte(s);short String s…

ChatGPT结合知识图谱构建医疗问答应用 (二) - 构建问答流程

一、ChatGPT结合知识图谱 上篇文章对医疗数据集进行了整理&#xff0c;并写入了知识图谱中&#xff0c;本篇文章将结合 ChatGPT 构建基于知识图谱的问答应用。 下面是上篇文章的地址&#xff1a; ChatGPT结合知识图谱构建医疗问答应用 (一) - 构建知识图谱 这里实现问答的流程…

前端后端路径问题详解

加了项目名&#xff0c;访问所有页面都是 在 项目名下 出来的路径 不加项目名&#xff0c;访问所有页面都不用加项目名&#xff0c;然后前后端的加/的效果都一样&#xff0c;都是在根目录下没有项目名的路径&#xff01;&#xff01;&#xff01; 后端 一、MVC 1.不管是转发…

小研究 - JVM GC 对 IMS HSS 延迟分析(二)

用户归属服务器&#xff08;IMS HSS&#xff09;是下一代通信网&#xff08;NGN&#xff09;核心网络 IP 多媒体子系统&#xff08;IMS&#xff09;中的主要用户数据库。IMS HSS 中存储用户的配置文件&#xff0c;可执行用户的身份验证和授权&#xff0c;并提供对呼叫控制服务器…

Segment anything(图片分割大模型)

目录 1.Segment anything 2.补充图像分割和目标检测的区别 1.Segment anything 定义&#xff1a;图像分割通用大模型 延深&#xff1a;可以预计视觉检测大模型&#xff0c;也快了。 进一步理解&#xff1a;传统图像分割对于下图处理时&#xff0c;识别房子的是识别房子的模型…

三数之和——力扣15

文章目录 题目描述法一 双指针排序 题目描述 法一 双指针排序 class Solution{ public:vector<vector<int>> threeSum(vector<int>& nums){int nnums.size();vector<vector<int>> ans;sort(nums.begin(), nums.end());for(int first0;first&…