<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot+Redis實現(xiàn)接口限流

          共 5358字,需瀏覽 11分鐘

           ·

          2022-03-03 01:00

          在這之前對redis一無所知,做的過程都是參考網(wǎng)上的資料,如果有冒犯之處請見諒,整理一下,希望對大家都用。

          1.使用maven添加依賴庫,本項目中使用的是:
          <dependency>
          ???<groupId>org.springframework.bootgroupId>
          ???<artifactId>spring-boot-starter-data-redisartifactId>
          ???<version>2.1.4.RELEASEversion>
          dependency>
          2.配置redis服務

          下載地址:

          https://github.com/MicrosoftArchive/redis/releases

          下載完成后啟動即可

          linux安裝教程可參考:

          https://blog.csdn.net/fm_vae/article/details/80234340

          3.回到正題,目的是使用redis達到接口限流的效果。

          定義一個注解標明需要使用限流的接口

          @Retention(RUNTIME)
          @Target(METHOD)
          public?@interface?AccessLimit?{
          ?
          ????int?seconds();
          ????int?maxCount();
          }

          在springboot的攔截器中,如果你沒有配置攔截器,需要自定義類繼承HandlerInterceptor

          ??@Override
          ????public?boolean?preHandle(HttpServletRequest?httpServletRequest,?HttpServletResponse?httpServletResponse,?Object?handler)?throws?Exception?{
          ????????//如果請求輸入方法
          ????????if?(handler?instanceof?HandlerMethod)?{
          ????????????HandlerMethod?hm?=?(HandlerMethod)?handler;
          ????????????//獲取方法中的注解,看是否有該注解
          ????????????AccessLimit?accessLimit?=?hm.getMethodAnnotation(AccessLimit.class);
          ????????????if?(accessLimit?!=?null)?{
          ????????????????long?seconds?=?accessLimit.seconds();
          ????????????????int?maxCount?=?accessLimit.maxCount();
          //關(guān)于key的生成規(guī)則可以自己定義?本項目需求是對每個方法都加上限流功能,如果你只是針對ip地址限流,那么key只需要只用ip就好
          ????????????????String?key?=?????SystemUtil.getClientIp(httpServletRequest)+hm.getMethod().getName();
          ??????????????
          ????????????????//從redis中獲取用戶訪問的次數(shù)
          ????????????????try?{
          ????????????????????long?q?=?redisService.incr(key,?seconds);//此操作代表獲取該key對應的值自增1后的結(jié)果
          ????????????????????if?(q?>?maxCount)?{
          ????????????????????????//加1
          ????????????????????????render(httpServletResponse,?new?ResponseMsg(0,?"請求過于頻繁,請稍候再試",?null));?//這里的CodeMsg是一個返回參數(shù)
          ????????????????????????return?false;
          ????????????????????}
          ????????????????????return?true;
          ????????????????}catch?(RedisConnectionFailureException?e){
          ????????????????????logger.info("redis錯誤"+e.getMessage().toString());
          ????????????????????return?true;
          ????????????????}
          ????????????}
          ?
          ????????}
          ?
          ?
          ????????return?false;
          ????}
          ?
          ????private?void?render(HttpServletResponse?response,?ResponseMsg?cm)?throws?Exception?{
          ????????response.setContentType("application/json;charset=UTF-8");
          ????????OutputStream?out?=?response.getOutputStream();
          ????????String?str?=?new?Gson().toJson(cm);
          ????????out.write(str.getBytes("UTF-8"));
          ????????out.flush();
          ????????out.close();
          ????}

          上面使用到的redisservice

          public?interface??RedisService?{
          ?
          ????/**
          ?????*?set存數(shù)據(jù)
          ?????*?@param?key
          ?????*?@param?value
          ?????*?@return
          ?????*/

          ????boolean?set(String?key,?String?value);
          ?
          ????/**
          ?????*?get獲取數(shù)據(jù)
          ?????*?@param?key
          ?????*?@return
          ?????*/

          ????String?get(String?key);
          ?
          ????/**
          ?????*?設置有效天數(shù)
          ?????*?@param?key
          ?????*?@param?expire
          ?????*?@return
          ?????*/

          ????boolean?expire(String?key,?long?expire);
          ?
          ????/**
          ?????*?移除數(shù)據(jù)
          ?????*?@param?key
          ?????*?@return
          ?????*/

          ????boolean?remove(String?key);
          ?
          ????/**
          ?????*?獲取自增1后的?值
          ?????*?@param?key
          ?????*?@param?time
          ?????*?@return
          ?????*/

          ????Long?incr(String?key,long?time);
          }

          redisservice的實現(xiàn)類

          @Service("redisService")
          public?class?RedisServiceImpl?implements?RedisService?{
          ?
          ?
          ????@Resource
          ????private?RedisTemplate?redisTemplate;
          ?
          ?
          ????@Override
          ????public?boolean?set(final?String?key,?final?String?value)?{
          ????????boolean?result?=?redisTemplate.execute(new?RedisCallback()?{
          ????????????@Override
          ????????????public?Boolean?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
          ????????????????RedisSerializer?serializer?=?redisTemplate.getStringSerializer();
          ????????????????connection.set(serializer.serialize(key),?serializer.serialize(value));
          ????????????????return?true;
          ????????????}
          ????????});
          ????????return?result;
          ????}
          ?
          ????@Override
          ????public?String?get(final?String?key)?{
          ????????String?result?=?redisTemplate.execute(new?RedisCallback()?{
          ????????????@Override
          ????????????public?String?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
          ????????????????RedisSerializer?serializer?=?redisTemplate.getStringSerializer();
          ????????????????byte[]?value?=?connection.get(serializer.serialize(key));
          ????????????????return?serializer.deserialize(value);
          ????????????}
          ????????});
          ????????return?result;
          ????}
          ?
          ????@Override
          ????public?boolean?expire(final?String?key,?long?expire)?{
          ????????return?redisTemplate.expire(key,?expire,?TimeUnit.SECONDS);
          ????}
          ?
          ????@Override
          ????public?boolean?remove(final?String?key)?{
          ????????boolean?result?=?redisTemplate.execute(new?RedisCallback()?{
          ????????????@Override
          ????????????public?Boolean?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
          ????????????????RedisSerializer?serializer?=?redisTemplate.getStringSerializer();
          ????????????????connection.del(key.getBytes());
          ????????????????return?true;
          ????????????}
          ????????});
          ????????return?result;
          ????}
          ????@Override
          ????public?Long?incr(String?key,long?time){
          ????????long?count?=?redisTemplate.opsForValue().increment(key,?1);
          ????????if?(count?==?1)?{
          ????????????//設置有效期一分鐘
          ????????????set(key,"1");
          ????????????redisTemplate.expire(key,?time,?TimeUnit.SECONDS);
          ????????}
          ????????return?count;
          ????}
          }

          至此限流的準備工作都做完了,測試一下ok,在controller方法中加上如下注解即可

          @AccessLimit(seconds=second,?maxCount=maxCount)

          測試通過。

          代碼大部分是從網(wǎng)上copy過來的,我只是整理了一下,因為我是隔了好久才整理的,至于copy的哪位大神的代碼我找不到了,如有冒犯,請見諒!

          來源:blog.csdn.net/qq_34963282/article/

          details/89489009


          END


          推薦閱讀

          一鍵生成Springboot & Vue項目!【畢設神器】

          Java可視化編程工具系列(一)

          Java可視化編程工具系列(二)


          順便給大家推薦一個GitHub項目,這個 GitHub 整理了上千本常用技術(shù)PDF,絕大部分核心的技術(shù)書籍都可以在這里找到,

          GitHub地址:https://github.com/javadevbooks/books

          電子書已經(jīng)更新好了,你們需要的可以自行下載了,記得點一個star,持續(xù)更新中..



          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕在线欧美 | 91AV电影在线观看 | 日本高清黄色视频 | 国产麻豆成人作品 | 亚洲一区二区三区污污污 |