使用AOP技术,记录项目中方法的执行时间

1.创建数据表

首先设计存储方法执行结果的数据表

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

2.添加注解

然后在启动类上添加@EnableAspectJAutoProxy注解,开启AOP服务.

3.创建日志类

@Component
@Aspect
public class LogAspect {
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private OperateLogMapper operateLogMapper;

    //自定义注解
    @Pointcut("@annotation(com.itheima.anno.LogAnno)")
    public void pt() {
    }

    //环绕通知
    @Around("pt()")
    public Object logAround(ProceedingJoinPoint pjp) {
        OperateLog operateLog = new OperateLog();

        //日志信息包含:方法作用、、返回值、方法执行时长
        try {
            String token = request.getHeader("token");
            Integer id = JwtUtils.parseJWT(token).get("id", Integer.class);
            operateLog.setOperateUser(id);//操作人id
        } catch (Exception e) {
            e.printStackTrace();
        }

        MethodSignature ms = (MethodSignature) pjp.getSignature();
        operateLog.setMethodName(ms.getMethod().getName());//方法名
        operateLog.setMethodDesc(ms.getMethod().getAnnotation(LogAnno.class).methodDesc());//方法作用

        operateLog.setOperateTime(LocalDateTime.now());//操作时间
        operateLog.setClassName(pjp.getTarget().getClass().getName());//全类名
        operateLog.setMethodParams(Arrays.toString(pjp.getArgs()));//参数

        Object obj = null;
        long start = new Date().getTime();
        try {
            obj = pjp.proceed();
            operateLog.setReturnValue(obj.toString());
            return obj;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
            long end = new Date().getTime();
            operateLog.setCostTime(end - start);//方法执行时长
            operateLogMapper.insert(operateLog);//保存日志
        }
    }
}

4.创建自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogAnno {
    String methodDesc() default "";//方法作用
}

5.将注解加到自己想要测试的类中,例如

    @LogAnno(methodDesc = "分页功能")
    @GetMapping("/emps")
    public Result findByPage(String name, String gender,
                             @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                             @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end,
                             @RequestParam(defaultValue = "1", name = "page") int index,
                             @RequestParam(defaultValue = "10", name = "pageSize") int page) {
        PageBean byPage = empService.findByPage(name, gender, begin, end, index, page);
        return Result.success(byPage);
    }

就可以记录该方法的执行时间了

另一种切点表达式

当需要测试的方法过多时,添加注解就不是一种合适的处理方式,我们可以通过@Pointcut指定一片区域来批量测试.在@Pointcut表达式中*指1或多个值,
..指0或多个值可以利用表达式指定一个范围内的所有方法
例如:

@Pointcut("execution(* com.itheima.controller.StudentController.*(..))")

你可能感兴趣的:(springboot)