美文网首页
自定义注解加AOP统计方法时长

自定义注解加AOP统计方法时长

作者: 不知不怪 | 来源:发表于2019-11-26 20:10 被阅读0次

    1.自定义注解

    package com.gzz.common.aop;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @类说明 [配合AOP统计时长的自定义注解类]
     * @author 高振中
     * @date 2019-11-26
     **/
    @Target({ ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CountTime {
        String app() default "";// 当前应用名
    
        String method() default "";// 当前方法名
    
        Class<?> clazz();// 当前类
    }
    

    2.切面类

    package com.gzz.common.aop;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * @类说明 [方法时长统计切面程序]
     * @author 高振中
     * @date 2019-11-26
     **/
    @Slf4j
    @Aspect
    @Component
    public class CountTimeAop {
        @Around("within(com.gzz..*) && @annotation(countTime) ")
        public Object ChangeRobotAops(ProceedingJoinPoint point, CountTime countTime) {
            Object proceed = null;
            String path = null;
            try {
                Long start = System.currentTimeMillis();
                proceed = point.proceed();// 调用目标方法
                path = countTime.clazz().getName() + "." + countTime.method();
                log.info("应用名:{},类名.方法名:{}(),耗时:{}毫秒", countTime.app(), path, System.currentTimeMillis() - start);
            } catch (Throwable e) {
                log.error("获取{" + path + "}方法消耗时长时发生异常!", e);
            }
            return proceed;
        }
    }
    

    3.使用

    
        /**
         * @方法说明:新增用户记录
         **/
        @CountTime(app = "plat", clazz = UserController.class, method = "save")
        @PostMapping("save")
        public int save(@RequestBody User user) {
            return service.save(user);
        }
    

    4.最终将数据落地,存入数据库

    package com.xsrt.plat.servercompute;
    
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentLinkedQueue;
    import java.util.stream.Collectors;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Service;
    
    import com.google.common.collect.Lists;
    import com.google.common.collect.Maps;
    import com.xsrt.beans.servercompute.ServerCompute;
    import com.xsrt.common.base.Page;
    
    /**
     * @author 高振中
     * @类说明 [服务管理]业务逻辑层
     * @date 2018-11-13 16:46:47
     **/
    @Service
    public class ServerComputeService {
        protected final Log logger = LogFactory.getLog(ServerComputeService.class);// 日志类
        private Map<String, ServerCompute> serverComputeCache = Maps.newHashMap();
    
        private ConcurrentLinkedQueue<ServerCompute> pushTaskQueue = new ConcurrentLinkedQueue<>();
    
        @Autowired
        private ServerComputeDao dao; // 注入服务管理数据访问层
    
        /**
         * @方法说明 按条件查询分页服务管理列表
         */
        public Page<ServerCompute> queryPage(ServerComputeCond cond) {
            return dao.queryPage(cond);
        }
    
        /**
         * @方法说明 请求进队列
         */
        public void add(ServerCompute serverCompute) {
            pushTaskQueue.offer(serverCompute);
        }
    
        /**
         * @方法说明 每隔50毫秒 取一个值进缓存
         */
        @Scheduled(fixedDelay = 50)
        private void putToCahce() {
            if (!this.pushTaskQueue.isEmpty()) {
                ServerCompute serverCompute = this.pushTaskQueue.poll();
                String key = serverCompute.getApp_name() + "_" + serverCompute.getServer_path();
                ServerCompute old = getOld(serverCompute, key);
                // 计算方法
                serverCompute.setSum_millisecond(old.getSum_millisecond() + serverCompute.getCurrent_millisecond());
                serverCompute.setMax_millisecond(Math.max(serverCompute.getCurrent_millisecond(), old.getMax_millisecond()));
                serverCompute.setMin_millisecond(Math.min(serverCompute.getCurrent_millisecond(), old.getMin_millisecond()));
                serverCompute.setSum_count(old.getSum_count() + 1);
                serverCompute.setAvg_millisecond((float) serverCompute.getSum_millisecond() / serverCompute.getSum_count());
                serverCompute.setCanSave(true);
                serverComputeCache.put(key, serverCompute);
            }
        }
    
        /**
         * @方法说明 取前一次的值
         */
    
        private ServerCompute getOld(ServerCompute serverCompute, String key) {
            ServerCompute old = serverComputeCache.get(key);
            if (old != null)
                return old;
            ServerComputeCond computeCond = ServerComputeCond.builder().server_path(serverCompute.getServer_path()).app_name(serverCompute.getApp_name()).build();
            List<ServerCompute> list = this.dao.queryList(computeCond);
            if (!list.isEmpty()) // 数据库中不存在的情况
                return list.get(0);
            old = new ServerCompute();
            old.setApp_name(serverCompute.getApp_name());
            old.setServer_path(serverCompute.getServer_path());
            return old;
        }
    
        /**
         * @方法说明 每隔30秒 入库一次
         */
        @Scheduled(fixedDelay = 30000)
        private void run() {
            List<ServerCompute> saveList = this.serverComputeCache.values().stream().filter(ServerCompute::isCanSave).collect(Collectors.toList());
            if (!saveList.isEmpty()) {
                Lists.partition(saveList, 500).forEach(this.dao::insertBatch);
                saveList.forEach(serverCompute -> serverCompute.setCanSave(false));
            }
        }
    
    }
    

    5.建表语句

    CREATE TABLE `admin_server_compute` (
      `server_path` varchar(200) NOT NULL COMMENT '接口路径',
      `app_name` varchar(20) NOT NULL COMMENT '应用名',
      `sum_count` bigint(20) DEFAULT NULL COMMENT '请求次数',
      `sum_millisecond` bigint(20) DEFAULT NULL COMMENT '请求总时长',
      `avg_millisecond` decimal(12,2) DEFAULT NULL COMMENT '请求平均时长',
      `max_millisecond` int(11) DEFAULT NULL COMMENT '请求最大时长',
      `min_millisecond` int(11) DEFAULT NULL COMMENT '请求最小时长',
      PRIMARY KEY (`server_path`,`app_name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
    

    相关文章

      网友评论

          本文标题:自定义注解加AOP统计方法时长

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