请使用Java代码实现通过注解传入用户id和每秒最大请求次数来实现限流的完整方案并解释相关代码
以下是一个简单的限流器的实现,使用了注解来指定用户id和每秒最大请求次数:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RateLimit {
int limit() default 5;
String key() default "";
}
这个注解有两个属性:
limit:每秒最大请求次数,默认为5次。key:用于区分不同用户的标识符,默认为空。
接下来是一个注解处理器,用于处理被@RateLimit注解的方法:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
@Component
public class RateLimitInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, Integer> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
RateLimit rateLimit = method.getAnnotation(RateLimit.class);
if (rateLimit != null) {
String key = rateLimit.key();
if (key.isEmpty()) {
key = request.getRemoteAddr();
}
int limit = rateLimit.limit();
Integer count = redisTemplate.opsForValue().get(key);
if (count == null) {
count = 1;
redisTemplate.opsForValue().set(key, count, 1, TimeUnit.SECONDS);
} else {
if (count < limit) {
count++;
redisTemplate.opsForValue().set(key, count, 1, TimeUnit.SECONDS);
} else {
response.setStatus(429);
return false;
}
}
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
这个处理器使用了Redis来记录每个用户在当前秒内的请求次数。如果请求次数超过了限制,就返回429状态码,表示请求过多。
最后,在Spring的配置文件中注册这个处理器:
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Autowired
private RateLimitInterceptor rateLimitInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(rateLimitInterceptor);
}
}
这样就完成了一个简单的限流器的实现。
原文地址: https://www.cveoy.top/t/topic/FsN 著作权归作者所有。请勿转载和采集!