• Springboot 打印接口耗时


    Springboot 打印 接口 耗时

    三种方式 下面为大家一一对应

    1 aop切面的方式 

    1.1 实现思路

    1. 引入aop依赖
    2. 自定义注解
    3. 定义切面,采用环绕通知

    1.2 代码实现

    1)引入依赖

            
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-aopartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2)自定义注解LogAnnotation

    /**
     * 日志注解
     * METHOD 方法上 type 类上
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface LogAnnotation {
    
        /**
         * 模块
         */
        String module() default "";
    
        /**
         * 简单描述接口的作用
         */
        String operation() default "";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3)定义切面

    简单分析一下切面实现的功能:

    /**
     * @author : look-word
     * 2022-07-27 16:03
     **/
    @Slf4j
    @Aspect
    @Component
    public class LogAspect {
    
        /**
         * 切入点
         */
        @Pointcut("@annotation(look.word.reggie.common.aop.LogAnnotation)")
        public void logPointCut() {
        }
    
        /**
         * 环绕通知
         *
         * @param point 连接点
         */
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            long beginTime = System.currentTimeMillis();
            //执行方法
            Object result = point.proceed();
            //执行时长(毫秒)
            long time = System.currentTimeMillis() - beginTime;
            //保存日志
            recordLog(point, time);
            return result;
        }
    
        private void recordLog(ProceedingJoinPoint joinPoint, long time) {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取当前方法
            Method method = signature.getMethod();
            LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
            log.info("=====================log start================================");
            log.info("module:{}", logAnnotation.module());
            log.info("operation:{}", logAnnotation.operation());
    
            //请求的方法名
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = signature.getName();
            log.info("request method:{}", className + "." + methodName + "()");
    
            //请求的参数
            Object[] args = joinPoint.getArgs();
            Stream<?> stream = ArrayUtils.isEmpty(args) ? Stream.empty() : Arrays.stream(args);
            List<Object> logArgs =
                    stream.filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse))).collect(Collectors.toList());
            String params = JSON.toJSONString(logArgs);
            log.info("params:{}", params);
    
            //获取request 设置IP地址
            HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
            log.info("ip:{}", IpUtils.getIpAddr(request));
            
            log.info("execute time : {} ms", time);
            log.info("=====================log end================================");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    1.3 功能测试

    在接口上添加注解即可,还有描述信息

    image-20220809221006438

    image-20220809221223447

    2 过滤器的方式

    这种方式简单点 但是可配置性不高

    **注意:**一定得扫描到spring容器中

    创建一个类 实现 filter接口

    • init:该方法是对filter对象进行初始化的方法,仅在容器初始化filter对象结束后被调用一次,参数FilterConfig可以获得filter的初始化参数;
    • doFilter:可以对request和response进行预处理其中FilterChain可以将处理后的request和response对象传递到过滤链上的下一个资源。
    • destroy():该方法在容器销毁对象前被调用。
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    @Component
    public class LogFilter implements Filter {
    
        private static final Logger LOG = LoggerFactory.getLogger(LogFilter.class);
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            // 打印请求信息
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            LOG.info("------------- LogFilter 开始 -------------");
            LOG.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
            LOG.info("远程地址: {}", request.getRemoteAddr());
    
            long startTime = System.currentTimeMillis();
            filterChain.doFilter(servletRequest, servletResponse);
            LOG.info("------------- LogFilter 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    结果
    img

    总结

    1.过滤器用来实现通用的功能,减少代码冗余,提高可维护性;
    2.一个过滤器可以配置给多个资源使用(编码过滤器);
    3.一个资源也可以配置多个过滤器,按照配置顺序调用。

    3 拦截器的方式

    如果不懂 请先看了 介绍再来

    拦截器的介绍

    话不说多 直接上代码

    创建拦截器

    /**
     * 拦截器:Spring框架特有的,常用于登录校验,权限校验,请求日志打印 /login
     * @author : look-word
     * 2022-06-26 13:55
     **/
    @Component
    public class LogInterceptor implements HandlerInterceptor {
        private static final Logger LOG = LoggerFactory.getLogger(LogInterceptor.class);
    
            
        @Override
         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
             // 打印请求信息
             LOG.info("------------- LogInterceptor 开始 -------------");
             LOG.info("请求地址: {} {}", request.getRequestURL().toString(), request.getMethod());
             LOG.info("远程地址: {}", request.getRemoteAddr());
    
             long startTime = System.currentTimeMillis();
             request.setAttribute("requestStartTime", startTime);
             return true;
         }
    
         @Override
         public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
             long startTime = (Long) request.getAttribute("requestStartTime");
             LOG.info("------------- LogInterceptor 结束 耗时:{} ms -------------", System.currentTimeMillis() - startTime);
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    注册拦截器

    把我们的拦截器 注册到 拦截器链中

    /**
     * @author : look-word
     * 2022-06-26 14:03
     **/
    @Configuration
    public class SpringMvcConfig implements WebMvcConfigurer {
    
        @Resource
        private LogInterceptor logInterceptor;
        /**
         * 注册拦截器
         * @param registry
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry
                    .addInterceptor(logInterceptor)
                    .addPathPatterns("/**")// 对那些接口拦截
                    .excludePathPatterns("/login");// 对哪些接机口放行
            WebMvcConfigurer.super.addInterceptors(registry);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    测试结果

    img

  • 相关阅读:
    考柏的感慨
    驱动开发之pinctrl 和 gpio 子系统
    把控元宇宙产业的发展脉络
    实战:如何优雅地扩展Log4j配置?
    springboot+vue“智慧食堂”设计与实现springboot002
    网络编程_fd_set结构
    Canal 1.1.5 数据库连接池报错问题解决
    lua如何调用C/C++
    刚毕业的学长真实体验:2022年软件测试行业不再吃香?毕业即失业?
    异常解决!针对文件I/O写入操作时FileNotFoundException异常的修复
  • 原文地址:https://blog.csdn.net/qq_50975965/article/details/126256783