简介
最近在做一个短链接的项目,其实应该是算改造,将原来的功能完善一下,其中就包括一个记录访问量的需求,需求大概是这样的:
根据每个链接记录其一定时间内的访问量,这个访问量应该是随时间动态变化,即使我不做什么操作。
最容易就想到利用Redis
的两种数据结构string
和hash
- string,
link:visit:$id:$date
需要通过时间来设置和查询,可单独设置过期时间,删除不能直接通过link来删除,只能自然过期?
设置和查询简单,不可单独设置过期时间,删除可一次性删除
当然我还看到有利用hyperloglog
记录访问集合的,这与我需求不符就不提了
开始吧
如标题所言,利用的就是AOP实现的
注解类
这种做法是有限制了,我也在下面写明了
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
|
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Visit {
String value();
String prefix();
long timeout() default 7L;
TimeUnit unit() default TimeUnit.DAYS; }
|
切面
前面也提到了,这个只适用于第一个参数是需要记录访问量的唯一id
,Redis
操作也是相当简单,”前缀+id
+时间“为key
,value
为数量就完事了
还有一个很重要的,这里设置的过期时间一直要和之后需要查询时间对应,也就是说设置了7天,之后查的也只能是7天,不然就不对了
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
|
@Aspect @Slf4j @Component @RequiredArgsConstructor public class VisitAspect {
private final ValueOperations<String, String> valueOperations;
@After("@annotation(visit)") public void after(JoinPoint point, Visit visit) { log.info("value {},prefix {},timeout {},unit {}", visit.value(), visit.prefix(), visit.timeout(), visit.unit()); Object[] args = point.getArgs(); String now = LocalDate.now().toString(); String key = RedisUtils.getKey(visit.prefix(), args[0], now); Object value = valueOperations.get(key); if (null != value) { valueOperations.increment(key); } else { valueOperations.set(key, "1", visit.timeout(), visit.unit()); } } }
|
放弃
也是因为上面说的那些缺点,最终还是放弃了这个方法
改回了每次访问主动地去操作redis
了😂
查询访问量
没什么说的
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
| @Override public Visits getVisits(Long id) { return getVisits(id, RedisUtils.TIME_OUT_30); }
@Override public Visits getVisits(Long id, long days) { LinkMap linkMap = baseMapper.selectById(id); if (null == linkMap) { return null; } LocalDate now = LocalDate.now(); Visits visits = new Visits(); int total = 0; List<VisitsVO> visitsVOList = new ArrayList<>(); for (int i = 0; i < days; i++) { String date = now.minusDays(i).toString(); String key = RedisUtils.getKey(CacheConstants.LINK_VISITS, id, date); String count = valueOperations.get(key); if (null == count || "0".equals(count)) { continue; } total += Integer.parseInt(count); VisitsVO visitsVO = new VisitsVO(); visitsVO.setDate(date); visitsVO.setCount(count); visitsVOList.add(visitsVO); } visits.setTotal(total); visits.setVisitsVOList(visitsVOList); return visits; }
|
总结
说到底,AOP实现的很不成熟,实战意义不大。
哈哈哈哈哈。。。。。