java sringboot 限制接口外部访问频率 每秒钟接口访问次数不得超过1次

逃离我推掉我的手 2023-10-10 16:49 140阅读 0赞

在Spring Boot中,可以通过AOP和Redis实现接口访问频率限制,限制每秒钟接口访问次数不得超过1次的方法如下:

引入Redis依赖
在pom.xml文件中添加Redis依赖:

xml

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>

配置Redis
在application.properties文件中配置Redis连接信息:

properties

  1. spring.redis.host=127.0.0.1
  2. spring.redis.port=6379
  3. spring.redis.password=
  4. spring.redis.database=0

编写AOP切面
创建一个切面类,用于限制接口的访问频率。在这个切面类中,我们需要使用Redis存储访问次数和时间戳,并根据设定的时间间隔和最大访问次数限制接口的访问频率。

  1. import java.util.concurrent.TimeUnit;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;
  4. import org.aspectj.lang.ProceedingJoinPoint;
  5. import org.aspectj.lang.annotation.Around;
  6. import org.aspectj.lang.annotation.Aspect;
  7. import org.aspectj.lang.annotation.Pointcut;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.data.redis.core.RedisTemplate;
  10. import org.springframework.stereotype.Component;
  11. import org.springframework.web.context.request.RequestContextHolder;
  12. import org.springframework.web.context.request.ServletRequestAttributes;
  13. @Aspect
  14. @Component
  15. public class RequestLimitAspect {
  16. private static final int SECOND = 1;
  17. private static final int MAX_COUNT = 1;
  18. @Autowired
  19. private RedisTemplate<String, String> redisTemplate;
  20. @Pointcut("@annotation(com.example.demo.annotation.RequestLimit)")
  21. public void requestLimit() {
  22. }
  23. @Around("requestLimit()")
  24. public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
  25. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  26. HttpServletRequest request = attributes.getRequest();
  27. HttpServletResponse response = attributes.getResponse();
  28. String ip = request.getRemoteAddr();
  29. String uri = request.getRequestURI();
  30. String key = "req_limit:" + ip + ":" + uri;
  31. String countStr = redisTemplate.opsForValue().get(key);
  32. if (countStr == null) {
  33. redisTemplate.opsForValue().set(key, "1", SECOND, TimeUnit.SECONDS);
  34. } else {
  35. int count = Integer.parseInt(countStr);
  36. if (count >= MAX_COUNT) {
  37. response.setStatus(429);
  38. return "Too many requests";
  39. }
  40. redisTemplate.opsForValue().set(key, String.valueOf(count + 1), SECOND, TimeUnit.SECONDS);
  41. }
  42. return joinPoint.proceed();
  43. }
  44. }

在上述代码中,我们首先使用@Autowired注解注入了RedisTemplate对象,该对象用于访问Redis数据库。然后,我们使用@Pointcut注解定义了一个切点requestLimit(),该切点表示被@RequestLimit注解标记的方法。接着,我们使用@Around注解定义了一个环绕通知,在被切入的方法执行前后执行该通知。在该通知中,我们首先获取请求的IP地址和URI,然后根据这些信息构建Redis的key值。如果该key值不存在,则将访问次数设置为1,并设置过期时间为1秒钟。如果该key值存在,则获取访问次数,如果访问次数超过1次,则返回429状态码和提示信息。否则,将访问次数加1,并将其存储到Redis中。

  1. 添加自定义注解
    创建一个自定义注解@RequestLimit,用于标记需要限制访问频率的方法:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RequestLimit {
    }

在接口方法上添加注解
在需要限制访问频率的接口方法上添加@RequestLimit注解:

  1. @RestController
  2. public class HelloController {
  3. @RequestLimit
  4. @GetMapping("/hello")
  5. public String hello() {
  6. return "Hello, World!";
  7. }
  8. }

在以上实现中,我们使用AOP和Redis实现了每秒钟接口访问次数不得超过1次的接口访问频率限制。具体实现可以根据实际需求进行调整。需要注意的是,以上代码可能会抛出Throwable异常,需要进行处理或抛出。

发表评论

表情:
评论列表 (有 0 条评论,140人围观)

还没有评论,来说两句吧...

相关阅读