1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Spring Boot 如何使用 Redis 進(jìn)行 API 防刷限流?

        共 3645字,需瀏覽 8分鐘

         ·

        2020-09-13 11:37

        Java技術(shù)棧

        www.javastack.cn

        關(guān)注閱讀更多優(yōu)質(zhì)文章



        限流的需求出現(xiàn)在許多常見(jiàn)的場(chǎng)景中:

        API 限流實(shí)戰(zhàn)

        首先我們編寫(xiě)注解類(lèi)AccessLimit,使用注解方式在方法上限流更優(yōu)雅更方便!Spring Boot 如何集成 Redis 請(qǐng)點(diǎn)擊這里進(jìn)行閱讀。

        三個(gè)參數(shù)分別代表有效時(shí)間、最大訪問(wèn)次數(shù)、是否需要登錄,可以理解為 seconds 內(nèi)最多訪問(wèn) 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;
        }

        限流的思路:

        • 通過(guò)路徑:ip的作為key,訪問(wèn)次數(shù)為value的方式對(duì)某一用戶(hù)的某一請(qǐng)求進(jìn)行唯一標(biāo)識(shí)

        • 每次訪問(wèn)的時(shí)候判斷key是否存在,是否count超過(guò)了限制的訪問(wèn)次數(shù)

        • 若訪問(wèn)超出限制,則應(yīng)response返回msg:請(qǐng)求過(guò)于頻繁給前端予以展示

        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;

        @Component
        public?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?????????????????redisService.inCr(key);
        ????????????????return?true;
        ????????????}

        ????????????if?(count?>=?maxCount)?{
        //????????????????response?返回?json?請(qǐng)求過(guò)于頻繁請(qǐng)稍后再試
        ????????????????return?false;
        ????????????}
        ????????}

        ????????return?true;
        ????}
        }

        注冊(cè)攔截器并配置攔截路徑和不攔截路徑:

        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?已經(jīng)廢棄,java?8開(kāi)始直接繼承就可以
        @Configuration
        public?class?IntercepterConfig??implements?WebMvcConfigurer?{
        ????@Autowired
        ????private?AccessLimtInterceptor?accessLimtInterceptor;

        ????@Override
        ????public?void?addInterceptors(InterceptorRegistry?registry)?{
        ????????registry.addInterceptor(accessLimtInterceptor)
        ????????????????.addPathPatterns("/攔截路徑")
        ????????????????.excludePathPatterns("/不被攔截路徑?通常為登錄注冊(cè)或者首頁(yè)");
        ????}
        }

        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?"";
        ????}
        }


        作者:海向

        出處:cnblogs.com/haixiang/p/12012728.html





        關(guān)注Java技術(shù)??锤喔韶?/strong>



        戳原文,獲取更多福利!
        瀏覽 33
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            永久免费无码A片在线观看大豆网 | 国产91在线 | 亚洲 | 99re6这里只有精品 | 操操免费网站 | 亚洲理论片 | 坐公交车被弄高潮几次 | 黄色大片在线免费观看 | 丰满放荡岳乱妇91www | 成人亚洲A片Ⅴ一区二区三区动漫 | 丁香五月天电影 |