在Spring Boot应用中限制请求访问次数可以通过几种不同的方法实现,如使用Rate Limiting中间件或自定义拦截器。以下是一些常见的实现方法:
方法1:使用Spring Boot内置的Rate Limiting工具
1.1 使用Bucket4j
Bucket4j是一个Java库,可以用来实现令牌桶算法的Rate Limiting。你可以通过以下步骤来集成Bucket4j:
步骤1:添加依赖
在pom.xml
中添加Bucket4j的依赖:
<dependency><groupId>com.github.vladimir-bukhtoyarov</groupId><artifactId>bucket4j-core</artifactId><version>6.2.0</version>
</dependency>
步骤2:创建配置类
创建一个Spring配置类来配置Rate Limiting:
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.time.Duration;@Configuration
public class RateLimiterConfig {@Beanpublic Bucket bucket() {Bandwidth limit = Bandwidth.classic(10, Refill.greedy(10, Duration.ofMinutes(1)));return Bucket4j.builder().addLimit(limit).build();}
}
步骤3:创建过滤器
创建一个过滤器来应用Rate Limiting:
import io.github.bucket4j.Bucket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Component
public class RateLimitFilter implements Filter {@Autowiredprivate Bucket bucket;@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {if (bucket.tryConsume(1)) {chain.doFilter(request, response);} else {HttpServletResponse httpResponse = (HttpServletResponse) response;httpResponse.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());httpResponse.getWriter().write("Too many requests");}}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}
}
步骤4:注册过滤器
在application.properties
或application.yml
中配置过滤器:
spring:web:filter:order: 1
方法2:使用Spring AOP实现Rate Limiting
通过Spring AOP(Aspect-Oriented Programming)也可以实现请求限制。
步骤1:创建自定义注解
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 RateLimit {int value();
}
步骤2:创建切面类
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;@Aspect
@Component
public class RateLimitAspect {private ConcurrentHashMap<String, Long> requestCounts = new ConcurrentHashMap<>();@Around("@annotation(rateLimit)")public Object rateLimit(ProceedingJoinPoint joinPoint, RateLimit rateLimit) throws Throwable {String key = joinPoint.getSignature().toShortString();requestCounts.putIfAbsent(key, 0L);long requests = requestCounts.get(key);if (requests >= rateLimit.value()) {throw new RuntimeException("Too many requests");} else {requestCounts.put(key, requests + 1);TimeUnit.MINUTES.sleep(1); // Reset the counter every minutereturn joinPoint.proceed();}}
}
步骤3:在需要限制的控制器方法上使用注解
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class MyController {@RateLimit(10)@GetMapping("/resource")public String getResource() {return "This is a rate-limited resource";}
}
这两种方法都可以有效地限制Spring Boot应用中的请求访问次数。第一种方法使用Bucket4j库实现了令牌桶算法,第二种方法通过Spring AOP实现了自定义的Rate Limiting逻辑。可以根据你的具体需求选择合适的方法。