springboot 自定义注解 ,实现接口限流(计数器限流)【强行喂饭版】
发布人:shili8
发布时间:2025-03-15 00:21
阅读次数:0
**SpringBoot 自定义注解实现接口限流**
在实际的开发中,我们经常会遇到需要对接口进行限流的需求。例如,某个接口每天只能被访问100次,这样可以防止恶意爬虫或其他程序过度地访问我们的接口,从而保护我们的系统不被滥用。
在SpringBoot中,我们可以使用自定义注解来实现接口限流。下面我们将一步步地讲解如何创建一个自定义注解,并且使用它来实现接口限流。
###1. 创建自定义注解首先,我们需要创建一个自定义注解,用于标记需要进行限流的接口。
javaimport java.lang.annotation.Documented;
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)
@Documentedpublic @interface LimitFlow {
int count() default100; // 每次限流的次数}
在上面的代码中,我们定义了一个名为`LimitFlow`的注解,使用了`@Target(ElementType.METHOD)`来指定该注解只能用于方法上。我们还设置了`count()`属性,表示每次限流的次数,默认值是100。
###2. 创建计数器接下来,我们需要创建一个计数器来记录每个接口被访问的次数。
javaimport java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class FlowCounter {
private ConcurrentHashMap flowMap = new ConcurrentHashMap<>();
public void addFlow(String key) {
AtomicInteger count = flowMap.get(key);
if (count == null) {
count = new AtomicInteger(0);
flowMap.putIfAbsent(key, count);
}
count.incrementAndGet();
}
public int getFlowCount(String key) {
return flowMap.getOrDefault(key, new AtomicInteger(0)).get();
}
}
在上面的代码中,我们定义了一个`FlowCounter`类,使用了`ConcurrentHashMap`和`AtomicInteger`来实现线程安全的计数器。
###3. 使用自定义注解现在,我们可以使用自定义注解来标记需要进行限流的接口。
java@RestController@RequestMapping("/api")
public class MyController {
@Autowired private FlowCounter flowCounter;
@GetMapping("/test")
@LimitFlow(count =50) // 每次限流的次数为50 public String test() {
return "Hello World!";
}
}
在上面的代码中,我们使用了自定义注解`@LimitFlow`来标记`test()`方法,每次限流的次数为50。
###4. 实现限流逻辑最后,我们需要实现限流逻辑。
javaimport org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptor;
import javax.servlet. />import javax.servlet. />import java.lang.reflect.Method;
public class FlowInterceptor implements HandlerInterceptor {
@Autowired private FlowCounter flowCounter;
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod) handler;
Method targetMethod = method.getMethod();
LimitFlow annotation = targetMethod.getAnnotation(LimitFlow.class);
if (annotation != null) {
String key = request.getRequestURI() + ":" + targetMethod.getName();
int count = flowCounter.getFlowCount(key);
if (count >= annotation.count()) {
throw new RuntimeException("接口被限流!");
}
flowCounter.addFlow(key);
}
}
return true;
}
}
在上面的代码中,我们实现了一个`FlowInterceptor`类,用于拦截需要进行限流的请求。我们使用自定义注解`@LimitFlow`来标记需要进行限流的接口,每次限流的次数为50。
###5. 配置拦截器最后,我们需要配置拦截器。
java@Configurationpublic class WebConfig implements WebMvcConfigurer {
@Bean public FlowInterceptor flowInterceptor() {
return new FlowInterceptor();
}
@Override public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(flowInterceptor()).addPathPatterns("/api/**");
}
}
在上面的代码中,我们配置了拦截器`flowInterceptor()`,并且添加了拦截规则`/api/**`。
通过以上步骤,我们就实现了一个自定义注解来进行接口限流。

