springboot项目对业务接口进行数据监控

文章介绍了如何使用AOP切面和自定义注解在Java项目中对请求次数、最大请求时间和总时间进行监控,以若依框架的RedisCache为例,并展示了如何在Controller和Service层应用此监控。
摘要由CSDN通过智能技术生成

需求:对请求次数、最大请求时间、请求时间总和等数据进行监控(参照durid  uri监控)

实现方案:aop切面+自定义注解方式实现

自定义注解类:
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface AroundLog{
    String flag() default "";
    int count() default 1;
}
Aspect切面类:(这里用的是若依的RedisCache缓存类  如果不是用的若依框架的话换成redis也一样)
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.lzqf.annotation.AroundLog;
import com.ruoyi.lzqf.domain.vo.InterfaceListenVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


@Aspect
@Slf4j
@Component
public class AroundLogAspect {

    @Autowired
    private RedisCache redisCache;

    @Around("@annotation(aroundLog)")
    public Object aroundLog(ProceedingJoinPoint point, AroundLog aroundLog) {
        List<InterfaceListenVo> list = new ArrayList<>();
        List<String> nameList = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        StopWatch started = new StopWatch();
        try {
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            sb.append("\n<===================================START===================================>\n");
            sb.append("call time:>").append(LocalDateTime.now()).append("\n");
            String methodName = method.getName();
            sb.append("method name:> ").append(methodName).append("\n");
            sb.append("log flag:> ").append(aroundLog.flag()).append("\n");
            started.start();
            Object proceed = point.proceed();
            return proceed;
        } catch (RuntimeException e) {
            sb.append("RuntimeException:>").append(e.getMessage()).append("\n");
            throw e;
        } catch (Throwable throwable) {
            sb.append("Throwable:>").append(throwable.getMessage()).append("\n");
            throw new RuntimeException("系统异常!");
        } finally {
            started.stop();
            sb.append("call total time(ms) :> ").append(started.getTime()).append("\n");
            sb.append("<====================================END====================================>\n");

            List<InterfaceListenVo> arrayList = new ArrayList<>();
            List<InterfaceListenVo> interfaceListen = redisCache.getCacheList("interfaceListen");
            if (interfaceListen.size() == 0) {
                InterfaceListenVo vo = new InterfaceListenVo();
                vo.setCount(aroundLog.count());
                vo.setInterfaceName(aroundLog.flag());
                vo.setRequestMaxTime(started.getTime());
                vo.setRequestTimeSum(started.getTime());
                //将vo对象放入集合中
                list.add(vo);
                redisCache.setCacheList("interfaceListen", list);
            }
            //如果interfaceListen集合中不为空   则遍历集合   将集合中的元素取出
            if (interfaceListen.size() >= 1) {
                interfaceListen.forEach(vo -> list.add(vo));
                interfaceListen.forEach(vo -> nameList.add(vo.getInterfaceName()));
            }
            redisCache.deleteObject("interfaceListen");

            //如果  当前正在执行的接口 接口名不在nameList集合中
            if(!nameList.contains(aroundLog.flag())){
                //则创建新的vo对象   将该对象放入arrayList集合中
                InterfaceListenVo vo1 = new InterfaceListenVo();
                vo1.setCount(aroundLog.count());
                vo1.setInterfaceName(aroundLog.flag());
                vo1.setRequestMaxTime(started.getTime());
                vo1.setRequestTimeSum(started.getTime());
                arrayList.add(vo1);
            }
            //将redis中的vo对象取出放入list集合中
            list.stream().forEach(vo -> {
                //如果  当前正在执行的接口 接口名在nameList集合中    并且当前正在执行的接口 接口名与正在遍历的vo对象名一样
                if (nameList.contains(aroundLog.flag()) && vo.getInterfaceName().equals(aroundLog.flag())){
                    //修改当前vo对象的值
                    vo.setCount(vo.getCount() + aroundLog.count());
                    vo.setRequestTimeSum(vo.getRequestTimeSum() + started.getTime());
                    vo.setRequestMaxTime(vo.getRequestMaxTime() > started.getTime() ? vo.getRequestMaxTime() : started.getTime());
                    arrayList.add(vo);
                    return;
                }
                arrayList.add(vo);
            });
            redisCache.setCacheList("interfaceListen",arrayList);
            log.info(sb.toString());
        }
    }
}
vo类:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class InterfaceListenVo {

    /**
     * 接口名
     */
    private String interfaceName;

    /**
     * 请求时间总和
     */
    private Long requestTimeSum;

    /**
     * 请求次数
     */
    private int count;

    /**
     * 请求时间最大值
     */
    private Long requestMaxTime;



}
使用:在你自己项目中的业务接口上加上@AroundLog(flag = "/flow/processes/export",count = 1)即可
    @AroundLog(flag = "/flow/processes/export",count = 1)
    @PreAuthorize("@ss.hasPermi('flow:processes:export')")
    @Log(title = "流程定义", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, LzqfBpmnInfo lzqfBpmnInfo)
    {
        List<LzqfBpmnInfo> list = lzqfBpmnInfoService.selectLzqfBpmnInfoList(lzqfBpmnInfo);
        ExcelUtil<LzqfBpmnInfo> util = new ExcelUtil<LzqfBpmnInfo>(LzqfBpmnInfo.class);
        util.exportExcel(response, list, "流程定义明细数据");
    }
controller层接口:
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/interface/listen")
public class InterfaceListenController {

    @Autowired
    private RedisCache redisCache;

    @Anonymous
    @GetMapping("/info")
    public AjaxResult queryInterfaceListenInfo(){
        return AjaxResult.success(redisCache.getCacheList("interfaceListen"));
    }


}

效果:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值