美文网首页一些收藏
利用AOP切面打印项目中每个接口的运行情况

利用AOP切面打印项目中每个接口的运行情况

作者: 追风人聊Java | 来源:发表于2021-11-24 09:16 被阅读0次

    1、前言

    AOP切面技术,大家应该都听知道,Spring框架的主要功能之一。

    AOP切面的用途很广,其中一个常见的用途就是打印接口方法的运行日志和运行时间。

    日志对于一个项目很是重要,不仅有助于调错,还是后期大数据分析的重要数据来源,这里我就简单介绍一下如何在SpringBoot中利用AOP切面打印后端接口的运行情况。

    2、切面代码

    实现方式很简单,在SpringBoot工程中,增加切面类,代码如下:

    import cn.zhuifengren.util.JsonUtils;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestAttributes;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @Aspect
    @Component
    @Order(Integer.MIN_VALUE)
    public class MyAspect {
    
        public static final Logger log =
                LoggerFactory.getLogger(MyAspect.class);
    
        @Around("execution(* cn.zhuifengren.controller..*Controller.*(..))")
        public Object recordTimeLog(ProceedingJoinPoint joinPoint) throws Throwable {
    
            // 记录开始时间
            long begin = System.currentTimeMillis();
    
            log.info("类信息:{}", joinPoint.getTarget().getClass());
            log.info("方法名:{}", joinPoint.getSignature().getName());
    
            // 获得request对象
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) requestAttributes;
            HttpServletRequest req = sra.getRequest();
            log.info("请求地址: {}",req.getRequestURI());
            log.info("请求设备: {}", req.getHeader("user-agent"));
    
            // 获得参数
            Object[] args = joinPoint.getArgs();
            if (args!=null && args.length>0){
                for (int i = 0; i < args.length; i++) {
                    if (args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse)
                        continue;
                    log.info("参数:" + ( args[i]==null? "": JsonUtils.objectToJson(args[i])));
                }
            }
    
            // 执行目标 service
            Object result = joinPoint.proceed();
            log.info("响应:" + JsonUtils.objectToJson(result));
    
            // 记录结束时间
            long end = System.currentTimeMillis();
            long time = end - begin;
    
            log.info("执行时间:{} 毫秒", time);
    
            return result;
        }
    
    }
    

    3、代码说明

    1)@Aspect 和 @Component 两个注解是切面类必须的,用于标识这是个切面类。

    2)@Order(Integer.MIN_VALUE) 注解用于设置切面的执行顺序,值越小,切面越早被执行。

    3)@Around("execution(* cn.zhuifengren.controller..Controller.(..))")

    众所周知,AOP切面的通知方式有5种,方法执行前通知、方法正常执行后通知、环绕通知、方法执行异常通知、最终通知。

    这里的 @Around 就是环绕通知,也就是方法执行前后都会通知。

    execution(* cn.zhuifengren.controller..Controller.(..)) 是切面表达式,用于指定哪些方法会被通知。

    第一个 * 代表方法返回类型 *代表所有类型;

    包名代表aop监控的类所在的包;

    .. 代表该包以及其子包下的所有类方法;

    *Controller 代表类名,代表所有以Controller结尾的类,如果包括所有类,则直接写 * ;

    *(..) 中 *代表类中的方法名,(..)表示方法中的任何参数。

    4)ProceedingJoinPoint joinPoint, 此对象是切面方法的参数,从中可以得到方法的请求参数,也用于执行方法得到响应值。

    5)joinPoint.getArgs() 获得参数。

    6)Object result = joinPoint.proceed(),执行方法,并得到返回值

    4、日志效果

    image

    相关文章

      网友评论

        本文标题:利用AOP切面打印项目中每个接口的运行情况

        本文链接:https://www.haomeiwen.com/subject/ovcntrtx.html