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 ConcurrentHashMapflowMap = 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/**`。
通过以上步骤,我们就实现了一个自定义注解来进行接口限流。