给工具的API做个统计
推荐视频和视频封面获取工具已经上线许久了,突发奇想看看每天是否有其他人在用呢,还是真的只有我和朋友在用。于是速速利用AOP1整了个统计功能,又利用echarts显示出来。
首先引入AOP需要的依赖
<!--引入AOP依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--AOP-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.12</version>
</dependency>
随后在启动类中添加相应注解
@EnableAspectJAutoProxy //AOP
@EnableScheduling //开启定时的注解,后面要用到
新建切面类ApiCallAdvice
@Component
@Aspect // 把类定义为切面供容器读取
@RequiredArgsConstructor
public class ApiCallAdvice {
private final RedisTemplate<String, String> redisTemplate;
@Resource
private StringRedisTemplate stringRedisTemplate;
private static final String FORMAT_PATTERN_DAY = "yyyy-MM-dd";
private Logger log = LoggerFactory.getLogger(ApiCallAdvice.class);
/**
* 如果有返回结果,代表一次调用,则对应接口的调用次数加一,统计维度为天
* (Redis使用Hash结构)
* key = URI
* key = date (精确到天)
* value = 调用次数
*/
@AfterReturning("execution(* com.java.service.controller.*.*(..))") //对controller下的所有接口进行监控
public void afterReturning() {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//获取请求的request
HttpServletRequest request = attributes.getRequest();
String uri = request.getRequestURI();
String date = dateFormat(FORMAT_PATTERN_DAY);
// 计数存入redis中
if (redisTemplate.hasKey(uri)) {
redisTemplate.opsForHash().increment(uri, date, 1);
} else {
redisTemplate.opsForHash().put(uri, date, "1");
redisTemplate.opsForHash().getOperations().expire(uri, 30, TimeUnit.DAYS);
}
}
private String dateFormat(String pattern) {
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
return dateFormat.format(new Date());
}
}
随后写进service里作为一个接口输出,方便前端获取统计的数据
最终获取到的JSON格式是这样的
"视频推荐工具": [
{
"count": "17", // 当天的统计量与时间,方便前端使用
"time": "2023-06-05"
},
{
"count": "68",
"time": "2023-06-06"
},
{
"count": "53",
"time": "2023-06-07"
}
后面测试发现,如果某天确实是没人用的话,没有调用接口,也就没有新一天的数据存入redis里,数据在echarts上就会很难看,于是决定在每天的0点01秒给redis中添加上一个占位的数据,计数为0
新建ScheduleTask
类
@Component
@RequiredArgsConstructor
public class ScheduleTask {
private final RedisTemplate<String, String> redisTemplate;
private static final String FORMAT_PATTERN_DAY = "yyyy-MM-dd";
@Scheduled(cron = "1 0 0 * * ?") // cron表达式,代表每天的0点0分1秒触发
public void CounterPlaceholder(){
ArrayList<String> list = new ArrayList<>();
list.add("/bili/推荐视频");
list.add("/bili/获取封面");
list.add("/bili/稍后再看");
String date = dateFormat(FORMAT_PATTERN_DAY);
for (String key : list){
// 如果已经有数据了的话...那就加一吧嘿嘿
if (redisTemplate.opsForHash().hasKey(key, date)) {
redisTemplate.opsForHash().increment(key, date, 1);
} else {
// 添加进redis占位
redisTemplate.opsForHash().put(key, date, "0");
redisTemplate.opsForHash().getOperations().expire(key, 30, TimeUnit.DAYS);
}
}
}
private String dateFormat(String pattern) {
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
return dateFormat.format(new Date());
}
}
至此,大功告成!
最终效果 API使用统计
- 面向切面编程 ↩