springBoot Aop 日志实现统计接口方法运行时间

1.添加sql脚本

- 记得添加aop和lombok依赖

- 运行sql脚本,在数据库中添加存储日志的数据库表

-- 操作日志表
create table operate_log(
    id int unsigned primary key auto_increment comment 'ID',
    class_name varchar(100) comment '操作的类名',
    method_name varchar(100) comment '操作的方法名',
    method_desc varchar(100) comment '方法用途',
    method_params varchar(1000) comment '方法参数',
    return_value varchar(2000) comment '返回值',
    operate_user int unsigned comment '操作人ID',
    operate_time datetime comment '操作时间',
    cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';

2.添加mysql语句

- 用于执行添加日志到数据库

-  SUBSTRING(#{returnValue},0,1500) : 如果日志查询到过多的数据会在函数里过滤掉

/**
 * 日志
 */
@Mapper
public interface OperateLogMapper {


    //插入日志数据
    //SUBSTRING(#{returnValue},0,1500)如果查询的的数据量过大需要使用subString函数来截取过多的数据
    @Insert("insert into db_health.operate_log (operate_user, operate_time, class_name, method_name,method_desc, method_params, return_value, cost_time) " +
            "values (#{operateUser}, #{operateTime}, #{className}, #{methodName},#{methodDesc}, #{methodParams}, SUBSTRING(#{returnValue},0,1500), #{costTime});")
    public void insert(OperateLog log);

}

3.添加实体类

- 用于封装查询到的日志数据

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * 日志实体类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id; //ID
    private String className; //操作类名
    private String methodName; //操作方法名
	private String methodDesc; //方法用途
    private String methodParams; //操作方法参数
    private String returnValue; //操作方法返回值
	private Integer operateUser; //操作人ID
    private LocalDateTime operateTime; //操作时间
    private Long costTime; //操作耗时
}
4.自定义日志注解

- 自定义的作用是标注需要切面的方法

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解 日志
 */
@Retention(RetentionPolicy.RUNTIME) //保留到运行阶段
@Target({ElementType.METHOD}) //标注在方法上
public @interface LogAnno {

    String methodDesc() default ""; //方法引用
}
5.使用Aop切面
package com.health.aspect;

import com.health.anno.LogAnno;
import com.health.domain.OperateLog;
import com.health.mapper.OperateLogMapper;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * AOP记录日志的切面
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private OperateLogMapper operateLogMapper;

    //切点 标注anno注解的方法都被切中
    @Pointcut("@annotation(com.health.anno.LogAnno)")
    public  void  cf(){}


    //环绕通知
    @Around("cf()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        OperateLog operateLog = new OperateLog();
        //获取类名
        operateLog.setClassName(pjp.getTarget().getClass().getName());
        //获取方法参数
        operateLog.setMethodParams(Arrays.toString(pjp.getArgs()));
        //import org.aspectj.lang.reflect.MethodSignature; 获取签名
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        //获取方法名
        operateLog.setMethodName(signature.getMethod().getName());

        LogAnno logAnno = signature.getMethod().getAnnotation(LogAnno.class);
        //获取方法描述
        operateLog.setMethodDesc(logAnno.methodDesc());

        String token = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(token);
        //拿到用户id
        Integer id = claims.get("id", Integer.class);
        //操作id
        operateLog.setOperateUser(id);*/
        //操作时间
        operateLog.setOperateTime(LocalDateTime.now());

        long begin = System.currentTimeMillis();
        Object object = pjp.proceed();
        long end = System.currentTimeMillis();

        //方法执行时间
        operateLog.setCostTime(end - begin);

        //方法返回信息  如果日志查询到的数据过多需要在sql语句 SUBSTRING(#{returnValue},0,1500),限定添加的字数
        operateLog.setReturnValue(object.toString());

        //落库
        operateLogMapper.insert(operateLog);
        return object;



    }

}
6.在需要执行的方法上添加@LogAnno(methodDesc = "xxx")注解
 @PutMapping
    @LogAnno(methodDesc = "修改部门数据")
    public Result updateDept(@RequestBody  Dept dept){
        deptService.updateDept(dept);
        return Result.success();

- 前端只要访问带有这个注解的方法,aop就会把数据添加到数据库的日志表中.

Spring Boot 中,可以通过 AOP(面向切面编程)来记录程序运行时间。具体实现步骤如下: 1. 创建一个切面类,使用 @Aspect 注解标识该类为切面类。 2. 定义一个方法,使用 @Around 注解标识该方法为环绕通知,即在目标方法执行前后都会执行该方法。 3. 在环绕通知方法中,使用 System.currentTimeMillis() 记录当前时间,执行目标方法,再次使用 System.currentTimeMillis() 记录当前时间,计算出程序运行时间。 4. 将程序运行时间记录日志中,可以使用 log4j2、slf4j 或者 Spring Boot 自带的日志框架。 下面是一个示例代码: ```java @Aspect @Component public class TimeAspect { private static final Logger logger = LoggerFactory.getLogger(TimeAspect.class); @Around("@annotation(com.example.demo.annotation.LogTime)") public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object result = joinPoint.proceed(); long end = System.currentTimeMillis(); logger.info("{} 方法执行时间为 {} ms", joinPoint.getSignature().getName(), end - start); return result; } } ``` 在上面的代码中,我们使用了 @LogTime 注解来标识需要记录程序运行时间方法。在环绕通知方法中,使用了 ProceedingJoinPoint 类来执行目标方法,最后将程序运行时间记录日志中。 需要注意的是,为了使切面生效,需要在 Spring Boot 的配置类中添加 @EnableAspectJAutoProxy 注解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值