使用aop统计接口调用次数,次数存储在redis中,超限会拦截,接口不被调用
定义注解类
/**
* ApiCallAnnotation
* 接口调用次数监控
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApiCallAnnotation {
String name() default "";
}
定义处理类
@Aspect
@Component
public class ApiCallAdvice{
@Autowired
private RedisTemplate redisTemplate;
private final static String DATE_FORMAT = "yyyy-MM-dd";
@Pointcut("@annotation(com.meiya.phonecloud.platform.annotation.ApiCallAnnotation)")
public void collect(){
}
/**
* 接口调用之前次数限制
* @param point
*/
@Before("collect()")
public void doBefore(JoinPoint point){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//获取接口设置的限制次数
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
ApiCallAnnotation annotation = method.getAnnotation(ApiCallAnnotation.class);
String value = annotation.name();
String redisKey = getRedisKey(attributes);
if(redisTemplate.hasKey(redisKey)){
int count = Integer.parseInt(redisTemplate.opsForValue().get(redisKey).toString());
if(StringUtils.isNotBlank(value)){
if(count==Integer.parseInt(value)){
throw new Exception("超出访问次数");
}
}
}
}
/**
* 接口调用之后添加次数
*/
@AfterReturning
public void AfterReturning(){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String redisKey = getRedisKey(attributes);
//获取key,如果存在加1,如果不存在设置key,并设置过期时间为1天
if(redisTemplate.hasKey(redisKey)){
redisTemplate.opsForValue().increment(1);
}else{
redisTemplate.opsForValue().set(redisKey,1,1L, TimeUnit.DAYS);
}
}
public String getRedisKey(ServletRequestAttributes attributes){
HttpServletRequest request = attributes.getRequest();
String uri = request.getRequestURI();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
LocalDateTime now = LocalDateTime.now();
String date = formatter.format(now);
String key = uri+"_"+date;
return key;
}
}
在需要拦截的接口上添加注释
@ApiCallAnnotation(name="10")