springboot不使用redis对指定接口限制访问次数代码实现
时间: 2023-12-05 20:04:06 浏览: 88
可以使用Spring AOP(面向切面编程)来实现接口限制访问次数的功能。
首先,需要定义一个注解来标识需要限制访问次数的接口,比如@AccessLimit:
```java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {
int seconds();
int maxCount();
}
```
然后,在AOP切面中实现对该注解的解析和限制访问次数的功能:
```java
@Aspect
@Component
public class AccessLimitAspect {
private final RedisTemplate<String, Integer> redisTemplate;
@Autowired
public AccessLimitAspect(RedisTemplate<String, Integer> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Around("@annotation(accessLimit)")
public Object around(ProceedingJoinPoint point, AccessLimit accessLimit) throws Throwable {
// 获取方法名和参数作为缓存的key
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
String methodName = method.getName();
Object[] args = point.getArgs();
String key = methodName + Arrays.toString(args);
// 获取当前时间戳和过期时间戳
long currentTime = System.currentTimeMillis();
long expireTime = currentTime + accessLimit.seconds() * 1000;
// 查询缓存中的访问次数
Integer count = redisTemplate.opsForValue().get(key);
if (count == null) {
// 缓存中没有该key,表示该接口第一次被访问,设置访问次数为1并设置过期时间
redisTemplate.opsForValue().set(key, 1, accessLimit.seconds(), TimeUnit.SECONDS);
} else {
if (count >= accessLimit.maxCount()) {
// 访问次数超过限制,返回错误信息
throw new RuntimeException("访问次数超过限制");
} else {
// 访问次数加1并更新过期时间
redisTemplate.opsForValue().increment(key, 1);
redisTemplate.expire(key, expireTime - currentTime, TimeUnit.MILLISECONDS);
}
}
// 执行目标方法
return point.proceed();
}
}
```
在这个切面中,我们使用了Redis作为缓存来存储接口的访问次数和过期时间。在每次访问被限制的接口时,我们先根据方法名和参数作为缓存的key查询缓存中的访问次数,如果缓存中没有该key,则表示该接口第一次被访问,设置访问次数为1并设置过期时间。如果缓存中已经有该key,则判断访问次数是否超过限制,如果超过限制则返回错误信息,否则访问次数加1并更新过期时间。最后执行目标方法。
要使用该AOP切面,只需要在需要限制访问次数的接口上添加@AccessLimit注解即可:
```java
@RestController
public class UserController {
@AccessLimit(seconds = 60, maxCount = 5)
@GetMapping("/user/info")
public String getUserInfo(@RequestParam("id") Integer id) {
// ...
}
}
```
这样,就可以对getUserInfo接口进行访问次数限制了。
阅读全文