公司的API接口被刷了,那是因为你没这样做
发布日期:2021-05-06 22:27:13 浏览次数:26 分类:原创文章

本文共 3905 字,大约阅读时间需要 13 分钟。

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

上一篇:

下一篇:

作者: 海向
来源: cnblogs.com/haixiang/p/12012728.html

api限流的场景

限流的需求出现在许多常见的场景中

1.秒杀活动,有人使用软件恶意刷单抢货,需要限流防止机器参与活动

2.某api被各式各样系统广泛调用,严重消耗网络、内存等资源,需要合理限流

3.淘宝获取ip所在城市接口、微信公众号识别微信用户等开发接口,免费提供给用户时需要限流,更具有实时性和准确性的接口需要付费。

api限流实战

首先我们编写注解类AccessLimit,使用注解方式在方法上限流更优雅更方便!三个参数分别代表有效时间、最大访问次数、是否需要登录,可以理解为 seconds 内最多访问 maxCount 次。

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface AccessLimit {    int seconds();    int maxCount();    boolean needLogin() default true;}

限流的思路

1.通过路径:ip的作为key,访问次数为value的方式对某一用户的某一请求进行唯一标识

2.每次访问的时候判断key是否存在,是否count超过了限制的访问次数

3.若访问超出限制,则应response返回msg:请求过于频繁给前端予以展示

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@Componentpublic class AccessLimtInterceptor implements HandlerInterceptor {    @Autowired    private RedisService redisService;    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        if (handler instanceof HandlerMethod) {            HandlerMethod hm = (HandlerMethod) handler;            AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);            if (null == accessLimit) {                return true;            }            int seconds = accessLimit.seconds();            int maxCount = accessLimit.maxCount();            boolean needLogin = accessLimit.needLogin();            if (needLogin) {                //判断是否登录            }            String key = request.getContextPath() + ":" + request.getServletPath() + ":" + ip ;            Integer count = redisService.get(key);            if (null == count || -1 == count) {                redisService.set(key, 1);                redisService.expire(seconds);                return true;            }            if (count < maxCount) {                redisService.inCr(key);                return true;            }            if (count >= maxCount) {// response 返回 json 请求过于频繁请稍后再试                return false;            }        }        return true;    }}

注册拦截器并配置拦截路径和不拦截路径

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;// extends WebMvcConfigurerAdapter 已经废弃,java 8开始直接继承就可以@Configurationpublic class IntercepterConfig  implements WebMvcConfigurer {    @Autowired    private AccessLimtInterceptor accessLimtInterceptor;    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(accessLimtInterceptor)                .addPathPatterns("/拦截路径")                .excludePathPatterns("/不被拦截路径 通常为登录注册或者首页");    }}

Controller层的方法上直接可以使用注解@AccessLimit

import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("test")public class TestControler {    @GetMapping("accessLimit")    @AccessLimit(seconds = 3, maxCount = 10)    public String testAccessLimit() {        //xxxx        return "";    }}

说句题外话,springboot全家桶技术交流群可以加我微信,但是坑位有限哦,由于忙于工作,有时不能及时回复大家,请多包涵。

猜你喜欢1、图文结合!一文搞懂 Redis 常用知识点!2、一个女生不主动联系你还有机会吗?3、基于Spring Security OAuth2.0实现单点登录SSO【完整源码】4、如果我是面试官,我会问你 Spring 那些问题?5、Mybatis的这些坑!把我坑惨了!6、某小型公司持续集成工具 jenkins 实践7、免费版的 IDEA 为啥不能使用 Tomcat ?8、做一个完整的Java Web项目需要掌握的技能强烈推荐一位大佬的公众号好文章,我在看❤️
上一篇:忘掉什么鬼并发,先听完这个故事!
下一篇:Java8解决了什么?

发表评论

最新留言

表示我来过!
[***.240.166.169]2025年04月12日 20时10分55秒