赞
踩
在Spring Boot中,可以通过AOP和Redis实现接口访问频率限制,限制每秒钟接口访问次数不得超过1次的方法如下:
引入Redis依赖
在pom.xml文件中添加Redis依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置Redis
在application.properties文件中配置Redis连接信息:
properties
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0
编写AOP切面
创建一个切面类,用于限制接口的访问频率。在这个切面类中,我们需要使用Redis存储访问次数和时间戳,并根据设定的时间间隔和最大访问次数限制接口的访问频率。
import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @Aspect @Component public class RequestLimitAspect { private static final int SECOND = 1; private static final int MAX_COUNT = 1; @Autowired private RedisTemplate<String, String> redisTemplate; @Pointcut("@annotation(com.example.demo.annotation.RequestLimit)") public void requestLimit() { } @Around("requestLimit()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); HttpServletResponse response = attributes.getResponse(); String ip = request.getRemoteAddr(); String uri = request.getRequestURI(); String key = "req_limit:" + ip + ":" + uri; String countStr = redisTemplate.opsForValue().get(key); if (countStr == null) { redisTemplate.opsForValue().set(key, "1", SECOND, TimeUnit.SECONDS); } else { int count = Integer.parseInt(countStr); if (count >= MAX_COUNT) { response.setStatus(429); return "Too many requests"; } redisTemplate.opsForValue().set(key, String.valueOf(count + 1), SECOND, TimeUnit.SECONDS); } return joinPoint.proceed(); } }
在上述代码中,我们首先使用@Autowired注解注入了RedisTemplate对象,该对象用于访问Redis数据库。然后,我们使用@Pointcut注解定义了一个切点requestLimit(),该切点表示被@RequestLimit注解标记的方法。接着,我们使用@Around注解定义了一个环绕通知,在被切入的方法执行前后执行该通知。在该通知中,我们首先获取请求的IP地址和URI,然后根据这些信息构建Redis的key值。如果该key值不存在,则将访问次数设置为1,并设置过期时间为1秒钟。如果该key值存在,则获取访问次数,如果访问次数超过1次,则返回429状态码和提示信息。否则,将访问次数加1,并将其存储到Redis中。
4. 添加自定义注解
创建一个自定义注解@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注解:
@RestController
public class HelloController {
@RequestLimit
@GetMapping("/hello")
public String hello() {
return "Hello, World!";
}
}
在以上实现中,我们使用AOP和Redis实现了每秒钟接口访问次数不得超过1次的接口访问频率限制。具体实现可以根据实际需求进行调整。需要注意的是,以上代码可能会抛出Throwable异常,需要进行处理或抛出。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。