首页 > 其他分享 >【Springboot】基于AOP实现操作日志记录

【Springboot】基于AOP实现操作日志记录

时间:2024-07-02 11:00:33浏览次数:3  
标签:Springboot 切入点 AOP 注解 日志 操作 方法

基于AOP实现操作日志记录

文章目录


前言

 在springboot项目中,往往需要在用户完成某些操作(例如:增,删,改)时,能够将相关操作信息记录下来,形成一个操作日志。
 操作日志信息包含:
操作人、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时长

所记录的日志信息包括当前接口的操作人是谁操作的,什么时间点操作的,以及访问的是哪个类当中的哪个方法,在访问这个方法的时候传入进来的参数是什么,访问这个方法最终拿到的返回值是什么,以及整个接口方法的运行时长是多长时间。

接下来将介绍如何利用AOP来实现操作日志的生成。

一、AOP

1.介绍

  • AOP英文全称:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。

 对于一个项目来讲,里面会包含很多的业务模块,每个业务模块又包含很多增删改查的方法,如果如果有一些功能需要我们要在每一个模块下的业务方法中,去实现,就会让程序员的工作变得非常繁琐。
 而AOP面向方法编程,就可以做到在不改动这些原始方法的基础上,针对特定的方法进行功能的增强。

AOP的作用:在程序运行期间在不修改源代码的基础上对已有方法进行增强(无侵入性: 解耦)

 比如说,我们要想完成统计各个业务方法执行耗时的需求,我们只需要定义一个模板方法,将记录方法执行耗时这一部分公共的逻辑代码,定义在模板方法当中,在这个方法开始运行之前,来记录这个方法运行的开始时间,在方法结束运行的时候,再来记录方法运行的结束时间,中间就来运行原始的业务方法,最后用结束时间减去开始时间即是执行这个方法所消耗的时间。

2.AOP核心概念

下面介绍一下AOP的几个核心概念:

1. 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)

​  连接点指的是可以被aop控制的方法。例如:入门程序当中所有的业务方法都是可以被aop控制的方法。
​  在SpringAOP提供的JoinPoint当中,封装了连接点方法在执行时的相关信息。
例:

 //环绕通知
    @Around("@annotation(com.ly.springbootdemotlias.anno.Log)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //获取目标类名
        String name = pjp.getTarget().getClass().getName();
        log.info("目标类名:{}",name);

        //目标方法名
        String methodName = pjp.getSignature().getName();
        log.info("目标方法名:{}",methodName);

        //获取方法执行时需要的参数
        Object[] args = pjp.getArgs();
        log.info("目标方法参数:{}", Arrays.toString(args));

        //执行原始方法
        Object returnValue = pjp.proceed();

        return returnValue;
    }

2. 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)

​  但是在AOP面向切面编程当中,我们只需要将这部分重复的代码逻辑抽取出来单独定义。抽取出来的这一部分重复的逻辑,也就是共性的功能。

Spring中AOP的通知类型:

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行
  • @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
  • @AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
  • @AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行
    注:只有@Around类型的通知需要用joinPoint.proceed();方法来调用连接点方法,且返回类型为Object

3. 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用

​  在通知当中,我们所定义的共性功能到底要应用在哪些方法上?此时就涉及到了切入点pointcut概念。切入点指的是匹配连接点的条件。通知仅会在切入点方法运行时才会被应用。
​  在aop的开发当中,我们通常会通过一个切入点表达式来描述切入点:
execution
execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:

execution(访问修饰符?  返回值  包名.类名.?方法名(方法参数) throws 异常?)

excution切入点表达式的语法规则:

  1. 方法的访问修饰符可以省略
  2. 返回值可以使用*号代替(任意返回值类型)
  3. 包名可以使用*号代替,代表任意包(一层包使用一个*
  4. 使用..配置包名,标识此包以及此包下的所有子包
  5. 类名可以使用*号代替,标识任意类
  6. 方法名可以使用*号代替,表示任意方法
  7. 可以使用 * 配置参数,一个任意类型的参数
  8. 可以使用.. 配置参数,任意个任意类型的参数
  9. 根据业务需要,可以使用 且(&&)、或(||)、非(!) 来组合比较复杂的切入点表达式。

    @annotation
    ​  如果我们要匹配多个无规则的方法,比如:list()和 delete()这两个方法。这个时候我们基于execution这种切入点表达式来描述就不是很方便了。而在之前我们是将两个切入点表达式组合在了一起完成的需求,这个是比较繁琐的。
    ​  我们可以借助于另一种切入点表达式annotation来描述这一类的切入点,从而来简化切入点表达式的书写。

实现步骤:

  1. 编写自定义注解
  2. 在业务类要做为连接点的方法上添加自定义注解

创建自定义注解
例:


@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target(ElementType.METHOD)//作用在方法上
public @interface Log {
}

在通知方法注解中用@annotation(注解全类名)声明这个通知方法的作用注解
例:

@Around("@annotation(com.ly.springbootdemotlias.anno.Log)")

最后在需要做为连接点的方法上添加自定义注解即可。
4. 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)

​ ​  当通知和切入点结合在一起,就形成了一个切面。通过切面就能够描述当前aop程序需要针对于哪个原始方法,在什么时候执行什么样的操作。

​ ​  切面所在的类,我们一般称为切面类(被@Aspect注解标识的类)
(注:切面类还需要加上@Component注解)

5. 目标对象:Target,通知所应用的对象

​​  目标对象指的就是通知所应用的对象,我们就称之为目标对象。

二、基于AOP实现操作日志记录

1.准备工作

首先需要导入AOP依赖
pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后需要创建日志记录数据库和实体类还有在Mapper层实现插入数据方法
实体类

//操作日志实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id; //主键ID
    private Integer operateUser; //操作人ID
    private LocalDateTime operateTime; //操作时间
    private String className; //操作类名
    private String methodName; //操作方法名
    private String methodParams; //操作方法参数
    private String returnValue; //操作方法返回值
    private Long costTime; //操作耗时
}

Mapper接口

@Mapper
public interface OperateLogMapper {

    //插入日志数据
    @Insert("insert into operate_log (operate_user, operate_time, class_name, method_name, method_params, return_value, cost_time) " +
            "values (#{operateUser}, #{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")
    public void insert(OperateLog log);

}

2.创建自定义注解和切面类

​ 因为我们要记录的操作日志是对于数据的增,删,改所以采用@annotation来指定要为连接点的方法。
​ 而且在涉及到消耗时间的字段,所以需要采用@Around通知类型
自定义注解类

@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target(ElementType.METHOD)//作用在方法上
public @interface Log {
}

切面类

@Aspect
@Component
public class LogAsper {
   @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired
    private HttpServletRequest request;

    @Around("@annotation(com.ly.springbootdemotlias.anno.Log)")//匹配加了Log注解的方法
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
       //方法开始前的操作
       
       //执行目标方法
        Object result = joinPoint.proceed();
        //方法结束后的操作
        
        return  result;

    }
}

3.实现日志记录

首先需要需要记录的操作接口方法前加上@Log注解
接下来在切面类中实现操作日志记录:

@Aspect
@Component
public class LogAsper {
    @Autowired
    private OperateLogMapper operateLogMapper;
    @Autowired
    private HttpServletRequest request;

    @Around("@annotation(com.ly.springbootdemotlias.anno.Log)")//匹配加了Log注解的方法
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        OperateLog operateLog = new OperateLog();
        //获取操作人id,通过获取并解析jwt令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJwt((jwt));
        Integer operateUser =(Integer) claims.get("id");
        operateLog.setOperateUser(operateUser);
        //获取操作时间
        operateLog.setOperateTime(LocalDateTime.now());
        //获取操作类名
        operateLog.setClassName(joinPoint.getTarget().getClass().getName());
        //获取操作方法名
        operateLog.setMethodName(joinPoint.getSignature().getName());
        //获取操作方法参数
        operateLog.setMethodParams(Arrays.toString(joinPoint.getArgs()));
        //获取开始时间
        long begin = System.currentTimeMillis();
        //获取操作方法返回值
        Object result = joinPoint.proceed();
        String returnValue = JSONObject.toJSONString(result);
        operateLog.setReturnValue(returnValue.toString());
        //获取操作结束时间
        long end = System.currentTimeMillis();
        //获取操作耗时
        operateLog.setCostTime((end-begin));
        operateLogMapper.insert(operateLog);
        return  result;

    }
}

总结

​  以上就是对于Spring项目中AOP的使用介绍,并且基于AOP实现了操作日志记录的功能,希望本文能给大家带来帮助。

标签:Springboot,切入点,AOP,注解,日志,操作,方法
From: https://blog.csdn.net/ASL2915/article/details/140117927

相关文章

  • springboot健身房管理系统-计算机毕业设计源码031807
    摘 要大数据时代下,数据呈爆炸式地增长。为了迎合信息化时代的潮流和信息化安全的要求,利用互联网服务于其他行业,促进生产,已经是成为一种势不可挡的趋势。在健身房管理的要求下,开发一款整体式结构的健身房管理系统,将复杂的系统进行拆分,能够实现对需求的变化快速响应、系统稳定......
  • 毕业设计-基于Springboot+Vue的班级综合测评管理系统的设计与实现(源码+LW+包运行)
    基于SpringBoot+Vue的班级综合测评管理系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1N_GWua74rAi1Qtkj1VpmHQ?pwd=zmut随着互联网技术的高速发展,人们生活的各方面都受到互联......
  • 毕业设计-基于Springboot+Vue的冬奥会科普系统的设计与实现(源码+LW+包运行)
    基于SpringBoot+Vue的冬奥会科普系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1YFTiNrYkLJAyvU40nmzbSg?pwd=x44b任何平台都要遵循平台设计的基本流程,本平台也不例外,同样需要......
  • 毕业设计-基于Springboot+Vue的校友社交系统的设计与实现(源码+LW+包运行)
    源码获取:https://download.csdn.net/download/u011832806/89460925基于SpringBoot+Vue的校友社交系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1gbqldVNoi7Shkp9jlM-fzg?pwd=tk......
  • 毕业设计-基于Springboot+Vue的毕业生信息招聘平台的设计与实现(源码+LW+包运行)
    源码获取:https://download.csdn.net/download/u011832806/89431634基于SpringBoot+Vue的毕业生信息招聘平台开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven系统演示视频:链接:https://pan.baidu.com/s/1-X-CEV8YNsWo7e-pA8pv7g?......
  • 基于java+springboot+vue实现的家政服务平台(文末源码+Lw)299
    摘 要现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本家政服务平台就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达......
  • 基于java+springboot+vue实现的旅游管理系统(文末源码+Lw)227
    摘 要现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本旅游管理系统就是在这样的大环境下诞生,其可以帮助使用者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达......
  • springboot3(cloud 2022.0.0)整合seata1.7.1
    一、第一步下载对应版本的seata服务  二、修改conf下的application.yml配置注意:主要是连接nacos的一些配置:注册中心和服务发现的配置1#Copyright1999-2019Seata.ioGroup.2#3#LicensedundertheApacheLicense,Version2.0(the"License");4#you......
  • RocketMQ 基础教程-RocketMQ整合SpringBoot
    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析......
  • 基于web的酒店客房管理系统 毕业设计 springboot+Vue+mysql
    介绍我开发了一个基于Web的酒店客房管理系统,旨在通过现代化的管理工具提升酒店客房管理的效率和用户体验。该系统分为管理员角色和用户角色,管理员负责管理用户、客房信息、预约、入住、退房等内容,用户则可以查询客房信息、进行预约、管理入住和退房等操作。系统通过丰富的功能......