首页 > 其他分享 >springboot 统计接口耗时及指定时间接口访问次数

springboot 统计接口耗时及指定时间接口访问次数

时间:2024-04-23 14:58:50浏览次数:26  
标签:springboot 接口 public 耗时 template new id redisTemplate

 

  1. 使用AOP在不改变原有方法的基础上对接口方法增强,引入依赖

<!--引入AOP依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--引入Redis依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

 

  2. 自定义注解,在需要统计耗时的接口上添加注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TakeCount {

    int time() default 60;
}

 

  3. 配置redis过期监听和redis配置类

  接口访问次数可以通过监听redis对应过期key来获取对应的访问次数

@Slf4j
public class KeyExpiredListener extends KeyExpirationEventMessageListener {

    @Autowired
    @Qualifier("myRedisTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private PrjAssignService prjAssignService;


    public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        //获取对应的接口访问次数
        log.info("{}接口在指定时间内被访问{}次",message,redisTemplate.opsForValue().get(message + ":count"));
        redisTemplate.delete(message + ":count");

//        PrjAssign one = prjAssignService.lambdaQuery().eq(PrjAssign::getId, "67f351605c0afe134e349e6d12434b48").one();
//        log.info(JSONUtil.toJsonStr(one));
    }
}
@Configuration
public class RedisConfiguration {


    @Autowired
    private RedisConnectionFactory redisConnectionFactory;


    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer() {
        RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
        redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
        return redisMessageListenerContainer;
    }

    @Bean
    public KeyExpiredListener keyExpiredListener() {
        return new KeyExpiredListener(this.redisMessageListenerContainer());
    }

    //配置Redis的字符串序列化,默认的为jdk本身的序列化,存储时会乱码
    @Bean("myRedisTemplate")
    @SuppressWarnings("all")
    public RedisTemplate redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        //key序列化
        template.setKeySerializer(new StringRedisSerializer());
        //value序列化
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        //hash的key序列化
        template.setHashKeySerializer(new StringRedisSerializer());
        //hash的value序列化
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        template.setConnectionFactory(factory);
        return template;
    }
}

 

  4. 定义AOP切面

  在使用了注解的接口上,会被spring扫描,当方法执行前会先执行doBefore()方法,记录开始时间访问次数,方法执行完成后执行doAfter()方法

@Slf4j
@Aspect
@Component
public class TakeCountAspect {

    @Autowired
    @Qualifier("myRedisTemplate")
    private RedisTemplate redisTemplate;

    //用threadlocal记录当前线程的开始访问时间
    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Before("@annotation(takeCount)")
    public void doBefore(TakeCount takeCount){
        //记录开始时间
        startTime.set(System.currentTimeMillis());
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //记录请求内容
        String url = request.getRequestURL().toString();
        //查询缓存中是否存在key并存储,存在+1,
        Boolean absent = redisTemplate.opsForValue().setIfAbsent(url, "num", takeCount.time(), TimeUnit.SECONDS);
        if (absent){
            redisTemplate.opsForValue().set(url + ":count",1);
        }else {
            redisTemplate.opsForValue().increment(url + ":count");
        }
    }

    @After("@annotation(TakeCount)")
    public void doAfter(JoinPoint point){
        log.info("{}访问耗时为:{}ms",point.getSignature().getName(),(System.currentTimeMillis() - startTime.get()));
    }
}

 

  5. 定义接口方法,在方法上使用注解

    /**
     * 通过id查询项目任务书
     * @param id id
     * @return R
     */
    @Operation(summary = "通过id查询", description = "通过id查询")
    @GetMapping("/{id}" )
    @TakeCount()
    public R getById(@PathVariable("id" ) String id) {
        return R.ok(prjAssignService.getByIdAssign(id));
    }

 

 

标签:springboot,接口,public,耗时,template,new,id,redisTemplate
From: https://www.cnblogs.com/homle/p/18152874

相关文章

  • springboot项目找不到符号问题以及模块聚合项目maven插件使用的相关问题 问题如图
    参考:https://www.cnblogs.com/coderxiaobai/p/15005181.html问题:更换maven,清空缓存重新导入依赖依然无效后(1)解决方法:方式一:删除项目中.idea文件夹,重新打开项目,选中jdk版本,重新导入依赖即可。(2)如果不是上述的原因可能是项目是模块聚合项目,原因就是父工程的pom中存在maven插......
  • SpringBoot如何优雅的进行参数校验(一)
    SpringBoot如何优雅的进行参数校验一.为什么要进行参数校验在日常的开发过程中,我们常常需要对传入的参数进行校验,比如在web前后端分离项目中,参数校验有两个方面:前端进行参数校验后端进行参数校验那这两种有什么区别呢?只完成一个可不可以呢?答案是不可以的!......
  • SpringBoot的Cookie sameSite之坑
    https://blog.csdn.net/weixin_38296425/article/details/111941318 CSDN上很多文章给出了解决CookiesameSite坑跨域之坑的解决办法,但是都忽略了一个问题,没有给出相关的依赖,我也是费了不少劲终于找到了解决办法,在这里记录下来。例如下面的代码:@ConfigurationpublicclassT......
  • feign调用接口报错No qualifying bean of type '***HttpMessageConverters' available
    在整合springcloudgeateway时,调用了feign接口,报错Noqualifyingbeanoftype'org.springframework.boot.autoconfigure.http.HttpMessageConverters'available报错信息feign.codec.EncodeException:Noqualifyingbeanoftype'org.springframework.boot.autocon......
  • SpringBoot3使用自带日志组件Logback
    参考:https://blog.csdn.net/AIJXB/article/details/128602818pom.xml<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></dependency>application.yaml配置l......
  • sh004基于springboot的MES生产制造执行系统【带LW文档】
    介绍基于springboot的MES生产制造执行系统管理员功能主要包括:生成计划管理、产品信息管理、销售订单管理、客户信息管理、物料信息管理、工业线路管理工序信息管理、员工管理、部门管理、个人中心等功能。员工功能结构图。其中员工查看工序信息,查看工艺线路,查看物料信息,查看产......
  • sh005基于springboot的景区订票系统【带LW文档】
    介绍基于springboot的景区订票系统管理员功能主要包括:个人中心、景点类型管理、公告类型管理、景点信息管理、公告信息管理、论坛管理、用户信息管理、轮播图管理、景点留言管理、景点收藏管理、景点预定管理等功能。由于本系统的功能模块设计比较全面,所以使得整个基于springbo......
  • 如何使用 Apifox 请求 gRPC 接口?
    使用Apifox发送gRPC接口Apifox支持基于.proto文件的gRPC调试,包括一元调用和流式调用。在创建项目时「选择gRPC项目」-->「导入.proto文件」,无需写代码即可直接调用gRPC接口。  创建gRPC在调试gRPC接口之前,也需要先导入作为API定义的.proto文件。如果......
  • 02 实现Runnable接口
    实现Runnable接口推荐使用Runnable对象,因为Java单继承的局限性。TestThread03.javapackagecom.mysoft.demo01;//创建线程方式2:实现runnalbe接口,重写run方法,执行线程需要丢入runnable接口实现类。调用start方法。publicclassTestThread03implementsRunnable{@Ov......
  • flutter 结合 springBoot 完成登录 注册 功能
    后端接口 前端调用接口代码import'package:dio/dio.dart';import'package:flutter/material.dart';import'../page/login.dart';//注册功能Future<void>register(BuildContextcontext,Stringusername,Stringpassword,......