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

AOP实现日志记录需求

首先创建annotation包,包下创建SystemLog类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface SystemLog {String businessName();
}

创建aspect包,包下创建LogAspect类

@Component
@Aspect
@Slf4j
public class LogAspect {@Pointcut("@annotation(com.zzq.annotation.SystemLog)")public void pt() {}@Around("pt()")public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable {Object ret ;try {handleBefore(joinPoint);ret = joinPoint.proceed();handleAfter(ret);} finally {//结束后换行log.info("=======End=======" + System.lineSeparator());}return ret;}private void handleAfter(Object ret) {// 打印出参log.info("Response      : {}",JSON.toJSONString(ret) );}private void handleBefore(ProceedingJoinPoint joinPoint) {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();//获取被增强方法上的注解对象SystemLog systemLog = getSystemLog(joinPoint);log.info("======= Start =======");// 打印请求 URL,增加空格使"URL:"和URL之间有一定间隔log.info("URL          : {}", request.getRequestURL());// 打印描述信息,同样增加空格log.info("BusinessName : {}", systemLog.businessName());// 打印 Http method,由于"HTTP Method"较长,可能需要更多空格来对齐log.info("HTTP Method  : {}", request.getMethod());// 打印调用 controller 的全路径以及执行方法,确保类名和方法名之间有适当的空格log.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());// 打印请求的 IPlog.info("IP           : {}", request.getRemoteHost());// 打印请求入参,如果参数较多或格式复杂,可能需要检查JSON.toJSONString的输出格式log.info("Request Args : {}", JSON.toJSONString(joinPoint.getArgs()));}private SystemLog getSystemLog(ProceedingJoinPoint joinPoint) {MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();SystemLog systemLog = methodSignature.getMethod().getAnnotation(SystemLog.class);return systemLog;}
}

@Component: 这个注解表明 LogAspect 是一个 Spring 组件,Spring 容器会管理这个类的实例。在 Spring AOP 中,这通常意味着这个类会被 Spring 自动检测和注册为一个切面(Aspect)。

@Aspect: 这个注解表明 LogAspect 是一个切面类,它定义了一个或多个通知(Advice)和切点(Pointcut)。切面类负责将通知织入到目标对象中。

@Slf4j: 这是 Lombok 库提供的一个注解,用于自动生成一个名为 log 的日志对象,该对象通常是 org.slf4j.Logger 类型。这使得在类中的任何地方都可以直接使用 log 对象进行日志记录。

@Pointcut(“@annotation(com.zzq.annotation.SystemLog)”): 这个注解定义了一个切点表达式,它指定了哪些方法应该被增强。具体来说,任何被@com.zzq.annotation.SystemLog 注解标记的方法都将被这个切点捕获。pt() 方法本身没有实现体,它只是作为一个切点表达式的声明。
环绕通知(Around Advice)
@Around(“pt()”): 这个注解定义了一个环绕通知,它会在目标方法执行之前和之后执行。环绕通知接收一个 ProceedingJoinPoint 参数,这个参数代表了目标方法的执行点。通过调用 joinPoint.proceed(),可以执行目标方法,并获取其返回值。
printLog 方法是环绕通知的实现。它首先尝试执行 handleBefore 方法来记录一些前置信息(如请求的 URL、HTTP 方法、类名和方法名等),然后调用 joinPoint.proceed() 来执行目标方法,并将返回值存储在 ret 变量中。之后,它调用 handleAfter 方法来记录后置信息(如响应结果)。无论目标方法是否成功执行,finally 块中的代码都会执行,以记录日志的结束标记。

handleBefore 方法:这个方法在目标方法执行之前被调用,用于记录请求的相关信息,如请求的 URL、HTTP 方法、IP 地址、请求参数以及业务名称(从 @SystemLog 注解中获取)。

handleAfter 方法:这个方法在目标方法执行之后被调用,用于记录响应结果。它使用 JSON.toJSONString(ret) 将响应结果转换为 JSON 字符串,并记录到日志中。

getSystemLog 方法:这个方法用于从目标方法上获取 @SystemLog 注解实例。它通过 joinPoint.getSignature() 获取到 MethodSignature,然后调用 getMethod() 获取到 Method 对象,最后从该对象上获取注解实例。

最后在方法中加入中

在这里插入图片描述

最后效果展示

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Python】 Python Schedule 模块:轻量级的定时任务调度库
  • docker 镜像站
  • Qt QLabel标签制作弹框效果,3s后缓慢自动消失
  • 如何在桌面同时展示多个窗口
  • Error hdl vendor backen is missing
  • 蒟蒻的尊严被打得一败涂地17
  • nginx基础配置
  • HTTP?HTTPS?HTTP2.0
  • 【GitHub】github clone远程仓库的时候一直失败
  • 【xilinx】O-RAN 无线电接口 - Vivado 2020.1 及更新工具版本的发行说明
  • fetch跨域请求数据的前端设置和后端php的header设置
  • 高性能web服务器--nginx
  • 【Datawhale X 魔搭 】AI夏令营第四期大模型方向,Task3:源大模型RAG实战(持续更新)
  • 【AI趋势8】具身智能
  • Leetcode 第 137 场双周赛
  • python3.6+scrapy+mysql 爬虫实战
  • [LeetCode] Wiggle Sort
  • Angular Elements 及其运作原理
  • CSS居中完全指南——构建CSS居中决策树
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • JavaScript HTML DOM
  • mockjs让前端开发独立于后端
  • node-glob通配符
  • XML已死 ?
  • 测试开发系类之接口自动化测试
  • 前端之Sass/Scss实战笔记
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 什么是Javascript函数节流?
  • 携程小程序初体验
  • 原生 js 实现移动端 Touch 滑动反弹
  • 自定义函数
  • (02)Unity使用在线AI大模型(调用Python)
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (理论篇)httpmoudle和httphandler一览
  • (十二)Flink Table API
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (算法)Travel Information Center
  • (五)activiti-modeler 编辑器初步优化
  • (译)2019年前端性能优化清单 — 下篇
  • .net程序集学习心得
  • .NET单元测试使用AutoFixture按需填充的方法总结
  • @media screen 针对不同移动设备
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)
  • [Algorithm][综合训练][拜访][买卖股票的最好时机(四)]详细讲解
  • [AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]
  • [Bugku]密码???[writeup]
  • [C puzzle book] types
  • [c++] 单例模式 + cyberrt TimingWheel 单例分析
  • [CF]Codeforces Round #551 (Div. 2)
  • [cocos2d-x]关于CC_CALLBACK
  • [HITCON 2017]SSRFme 1
  • [nsight compute使用指南] 查看存储体冲突
  • [Oh My C++ Diary]善用三目运算符(a?b:c)
  • [Oracle]如何观察Table 的各种Lock 之间的冲突
  • [P4V]Perforce(P4V)使用教程