【切面编程】自定义注解实现操作日志

news2024/12/23 10:44:32

创建一个项目工程

引入相关依赖

<!-- aop切面 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- lombok -->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>

新建一个自定义注解

/**
 * @date 2024/7/31 20:09
 * @description 日志注解
 */
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {

    /**
     * 模块名称
     *
     * @return
     */
    String title() default "";

    /**
     * 业务类型
     *
     * @return
     */
    String businessType() default "";
}

创建相关的切面类

package com.demo.demos.web.aspect;

import com.demo.demos.web.annotation.Log;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;

/**
 * @date 2024/7/31 20:12
 * @description 自定义日志注解切面类
 */
@Slf4j
@Aspect
@Component
public class LogAspect {


    /**
     * 定义切点表达式,用于识别需要进行日志记录的方法。
     * 该切点表达式指定了标注有特定注解的方法,即使用了com.demo.demos.web.annotation.Log注解的方法。
     * 这样做的目的是为了在这些方法执行前后插入日志记录的逻辑,而不需要直接修改这些方法的代码。
     */
    private static final String POINT_CUT = "@annotation(com.demo.demos.web.annotation.Log)";

    /**
     * 定义一个切点方法,无参数无返回值。
     * 该方法的存在是为了配合切点表达式使用,切点表达式定义了哪些方法应该被这个切点方法影响。
     * 在这个例子中,@Pointcut注解将log()方法与POINT_CUT定义的切点表达式关联起来,
     * 使得任何符合切点表达式的方法都会受到通知(Advice)的影响,
     * 这里的通知可能是记录日志、性能监控等切面逻辑。
     */
    @Pointcut(POINT_CUT)
    private void log() {

    }

    /**
     * 定义一个环绕通知方法,用于在目标方法执行前后进行日志记录。
     * 该方法接收一个ProceedingJoinPoint类型的参数,用于获取目标方法的相关信息,
     * 并在目标方法执行前后进行日志记录。
     *
     * @param joinPoint ProceedingJoinPoint类型的参数,用于获取目标方法的相关信息
     * @return 目标方法的返回值
     * @throws Throwable 目标方法抛出的异常
     */
    @Around("log()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 请求开始时间
        long startTime = System.currentTimeMillis();
        log.info("请求开始时间:{}", startTime);

        // 获取注解所在方法上的相关参数
        Object[] args = joinPoint.getArgs();
        log.info("请求参数:{}", args);

        Log apiLog = getApiOperationLogDescription(joinPoint);
        if (apiLog != null) {
            log.info("请求标题:{}", apiLog.title());
            log.info("请求类型:{}", apiLog.businessType());
        }


        Object result = joinPoint.proceed();
        log.info("请求返回值:{}", result);

        // 执行耗时
        long executionTime = System.currentTimeMillis() - startTime;
        log.info("请求执行耗时:{}", executionTime);

        return result;
    }


    /**
     * 获取方法上的日志注解实例。
     * 该方法旨在通过反射机制,从给定的 ProceedingJoinPoint 中提取目标方法的信息,
     * 并进一步获取该方法上是否标注了 Log 注解,从而为后续的日志记录提供必要的配置信息。
     *
     * @param joinPoint 切点对象,包含目标方法的详细信息。
     * @return 返回目标方法上标注的 Log 注解实例,如果不存在则返回 null。
     */
    private Log getApiOperationLogDescription(ProceedingJoinPoint joinPoint) {
        // 将 ProceedingJoinPoint 转换为 MethodSignature,以便获取方法相关的信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 通过 MethodSignature 获取目标方法对象
        Method method = signature.getMethod();
        // 从方法上尝试获取 Log 注解实例
        Log log = method.getAnnotation(Log.class);
        // 返回 Log 注解实例,如果方法上没有标注 Log 注解,则返回 null
        return log;
    }
}

创建测试类

/**
 * @date 2024/7/31 20:24
 * @description
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @Log(title = "测试管理", businessType = "测试")
    @RequestMapping("/test")
    public String test(String body) {
        return body;
    }
}

image.png

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

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

相关文章

24导游证报名照片要求是什么❓整理好了❗

24导游证报名照片要求是什么❓整理好了❗ 导游资格考试今天开始报名啦&#xff01; ⚠️考生们注意&#xff0c;需要上传免冠证件照、身份证扫描件、学历证明等照片信息&#xff01; ⚠️这里需要注意一下上传的照片文件信息规格&#xff0c;否则上传失败&#xff0c;无法完…

中国星坤耳机插座系列:空间与音质的体验升级

在现代电子设备日益普及的今天&#xff0c;耳机插座作为连接音频设备与用户的重要接口&#xff0c;其设计和性能直接影响着用户的听觉体验。中国星坤耳机插座以其精巧的设计和卓越的性能&#xff0c;为用户提供了既节省空间又保证音质的解决方案。本文将探讨星坤耳机插座的特点…

Vue3_对接声网实时音视频_多人视频会议

目录 一、声网 1.注册账号 2.新建项目 二、实时音视频集成 1.声网CDN集成 2.iframe嵌入html 3.自定义UI集成 4.提高进入房间速度 web项目需要实现一个多人会议&#xff0c;对接的声网的灵动课堂。在这里说一下对接流程。 一、声网 声网成立于2014年&#xff0c;是全球…

知乎信息流广告怎么投?一文读懂知乎广告开户及投放!

作为中国领先的问答社区&#xff0c;知乎以其高质量的内容和活跃的用户群体成为了众多品牌青睐的营销阵地。为了帮助企业更高效地利用知乎平台进行品牌推广&#xff0c;云衔科技提供了全方位的知乎广告开户及代运营服务&#xff0c;助力您的品牌在知乎上实现快速增长。 一、知…

提单和提货单有什么区别❓一文读懂‼️

提货单与提单的区别 在国际贸易和物流领域中&#xff0c;提货单&#xff08;D/O&#xff09;和提单&#xff08;B/L&#xff09;是两个关键的单据&#xff0c;它们在货物清关和提货过程中扮演着重要角色。以下是对这两个单据的详细解释和它们之间的区别。 提货单&#xff08;…

pdf文件怎么删除页面?看完就能学会的四种删除pdf页面方法!

pdf文件怎么删除页面&#xff1f;在日常使用PDF文档的过程中&#xff0c;我们时常会遇到一些没必要存在的页面&#xff0c;保留这些页面可能带来多重不利影响&#xff0c;首先它们会打断阅读的流畅性&#xff0c;这会让人在阅读时感到突兀与不适&#xff0c;其次&#xff0c;这…

CentOS7下搭建配置SVN服务器

1、通过yum安装subversion&#xff0c;根据提示完成安装 <span style"color:#333333"><span style"background-color:#f5f5f5">sudo yum install subversion</span></span> subversion安装在/bin目录 <span style"colo…

蓝桥杯 Python 研究生组-2023-省赛-工作时长

蓝桥账户中心https://www.lanqiao.cn/problems/3494/learning/ 问题描述 小蓝手里有一份 20222022 年度自己的上班打卡记录文件&#xff0c;文件包含若干条打卡记录&#xff0c;每条记录的格式均为“yyyy-MM-dd HH:mm:ssyyyy-MM-dd HH:mm:ss”&#xff0c;即按照年-月-日 时:…

专业级翻译解决方案:2024年商务翻译工具精选

现在科技发达了&#xff0c;不会外语也不怕了&#xff08;因为可以借助很多翻译工具解决这个头疼的问题啦&#xff09;。如果说到翻译你想到的还是百度翻译&#xff0c;那你可以拓宽一些翻译工具待用库啦。现在有不少多功能&#xff0c;好用的翻译软件咯。 1.福昕在线翻译 链…

矿用综采工作面软件开发

故障诊断算法软件界面设计实时监测故障机理分析实时故障诊断 1.软件原型图 2.通信协议

SpringBoot集成GraalVM创建高性能原生镜像

1. GraalVM 原生镜像的介绍 GraalVM原生镜像为部署和运行Java应用程序提供了一种新的方式。与Java虚拟机相比&#xff0c;原生镜像可以以更小的内存占用和更快的启动时间运行。 它们非常适用于使用容器镜像部署的应用程序&#xff0c;当与 "功能即服务"&#xff08…

vue3 主页面 跳转到子页面后 ,再次切换到主页面后 主页面及其它的所有页面 竟然不显示了的解决。

1、child 子页面是这样写的&#xff0c;先上个代码图&#xff0c;template里面包含了Tabs,还有一个Modal(这个是后来加的&#xff09; 2、然后从parent跳转到了这个child&#xff0c;再次切换到parent页面时&#xff0c;什么页面的视图都不显示出来了 3、然后我们可以看到chi…

MySQL:初识数据库初始SQL创建数据库

目录 1、初始数据库 1.1 什么是数据库 1.2 什么是MySQL 2、数据库 2.1 数据库服务&数据库 2.2 C/S架构 3、 初始SQL 3.1 什么是SQL 3.2 SQL分类 4、使用SQL 4.1 查看数据库 4.1.2 语句解析 4.2 创建数据库 4.2.1 if not exists校验 4.2.2 手动明确字符集和排…

GPT 和 BERT 系列论文阅读总结

文章目录 1. GPT1.1 GPT的目的和任务1.2 GPT的实现1.2.1 Unsupervised pre-training1.2.2 Supervised fine-tuning1.2.3 特定任务的输入格式 2. BERT2.1 BERT的目的和任务2.2 BERT的实现2.2.1 Masked Language Model2.2.2 Next Sentence Prediction (NSP) 3. GPT-23.1 初见 pro…

HCL实验2:VLAN

目的&#xff1a;让PC_3和PC_5处于vlan1, PC_4和PC_6处于vlan2 SW1的配置命令: vlan 2 port GigabitEthernet 1/0/2 quit int g1/0/3 port link-type trunk port trunk permit vlan all quit SW2的配置命令&#xff1a; vlan 2 port GigabitEthernet 1/0/2 quit int g1/0/3 p…

黑马Java零基础视频教程精华部分_8_学生管理系统

系列文章目录 文章目录 系列文章目录一、业务分析二、结合业务流程图编写代码1、Student.java代码&#xff1a;2、StudentSystem.java代码&#xff1a;3、标号&#xff08;‌label&#xff09;‌ 三、学生管理系统升级版 一、业务分析 需求文档如图所示&#xff1a; 根据需求…

在线招投标系统在线编辑Word且兼容微软Office和金山WPS

随着信息技术的不断发展&#xff0c;电子政务已经非常普及&#xff0c;电子招投标行业市场规模不断扩大&#xff0c;电子招投标不仅可以减少繁琐的人工操作&#xff0c;提高工作效率&#xff0c;还能保证公开透明的招标流程&#xff0c;制作招标文件过程中&#xff0c;由于微软…

pikachu:XXE

判断是否有xxe漏洞&#xff0c;如果返回了 xxe 就是有 <?xml version "1.0"?> <!DOCTYPE a [<!ENTITY b "xxe">]><c>&b;</c> 读取敏感文件 <?xml version "1.0"?> <!DOCTYPE ANY [ <!ENT…

Hbuilder x 解决打开内置终端或者控制台空白

文章目录 目录 文章目录 流程 小结 概要教程技术细节小结 概要 解决方式有3种 问题展示&#xff0c;如图所示&#xff1a; 其实忽略了一个本身的问题&#xff0c;小问题。打开控制终端没有显示可能是你还没有点击 以上细节没有问题还是没有解决的话&#xff0c;请根据二种方式…

Express基于Node.js基础知识【2】全面总结 推荐

最近在用基于node.js平台的web应用开发做项目&#xff0c;梳理了下关于Express框架的相关知识&#xff0c;方便自己以后查看&#xff0c;希望也能帮助证字啊学习express相关知识的同学&#xff0c;欢迎大家参考&#xff0c;有问题评论区留言&#xff0c;谢谢。 Node.js下载安装…