最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot通過(guò)攔截器實(shí)現(xiàn)接口限流的兩種方案

 更新時(shí)間:2025年10月11日 10:36:23   作者:IT橘子皮  
在Spring Boot中,可以通過(guò)自定義攔截器(Interceptor)結(jié)合Redis或內(nèi)存計(jì)數(shù)器實(shí)現(xiàn)接口限流,以下是兩種典型實(shí)現(xiàn)方式及代碼示例,需要的朋友可以參考下

在Spring Boot中,可以通過(guò)自定義攔截器(Interceptor)結(jié)合Redis或內(nèi)存計(jì)數(shù)器實(shí)現(xiàn)接口限流。以下是兩種典型實(shí)現(xiàn)方式及代碼示例:

?方案一:基于Redis + Lua腳本的分布式限流?

?核心邏輯?

  1. ?Redis配置?:使用Lua腳本保證原子性操作(計(jì)數(shù)+過(guò)期時(shí)間設(shè)置)。
  2. ?攔截器?:攔截請(qǐng)求,通過(guò)Redis統(tǒng)計(jì)IP或用戶維度的訪問(wèn)次數(shù)。
  3. ?注冊(cè)攔截器?:指定攔截路徑和排除路徑。

?代碼實(shí)現(xiàn)?

1. Redis配置類

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }

    @Bean
    public DefaultRedisScript<Long> rateLimitScript() {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptText(
            "local key = KEYS[1]\n" +
            "local limit = tonumber(ARGV[1])\n" +
            "local expire = tonumber(ARGV[2])\n" +
            "local current = redis.call('INCR', key)\n" +
            "if current == 1 then\n" +
            "    redis.call('EXPIRE', key, expire)\n" +
            "end\n" +
            "return current > limit and 1 or 0"
        );
        script.setResultType(Long.class);
        return script;
    }
}

2. 限流攔截器

@Component
public class RateLimitInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private DefaultRedisScript<Long> rateLimitScript;

    private static final int DEFAULT_LIMIT = 60; // 每分鐘60次
    private static final int DEFAULT_TIMEOUT = 60; // 60秒過(guò)期

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        String ip = request.getRemoteAddr();
        String uri = request.getRequestURI();
        String key = "rate_limit:" + ip + ":" + uri.split("/")[1]; // 按接口前綴分組

        Long result = redisTemplate.execute(
            rateLimitScript,
            Collections.singletonList(key),
            DEFAULT_LIMIT, DEFAULT_TIMEOUT
        );

        if (result != null && result == 1) {
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.getWriter().write("Too many requests");
            return false;
        }
        return true;
    }
}

3. 注冊(cè)攔截器

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private RateLimitInterceptor rateLimitInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(rateLimitInterceptor)
            .addPathPatterns("/api/**")
            .excludePathPatterns("/api/login");
    }
}

?方案二:基于內(nèi)存計(jì)數(shù)器的單機(jī)限流?

?核心邏輯?

  1. ?攔截器?:使用ConcurrentHashMap存儲(chǔ)IP和訪問(wèn)時(shí)間戳。
  2. ?滑動(dòng)窗口?:統(tǒng)計(jì)1分鐘內(nèi)的請(qǐng)求數(shù),超限則拒絕。

?代碼實(shí)現(xiàn)?

public class RateLimitingInterceptor implements HandlerInterceptor {
    private final ConcurrentMap<String, Long> requestCounts = new ConcurrentHashMap<>();
    private static final long ALLOWED_REQUESTS_PER_MINUTE = 60;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String clientIp = request.getRemoteAddr();
        long currentTime = System.currentTimeMillis();

        // 清理過(guò)期請(qǐng)求
        requestCounts.entrySet().removeIf(entry -> 
            currentTime - entry.getValue() > TimeUnit.MINUTES.toMillis(1)
        );

        // 統(tǒng)計(jì)當(dāng)前窗口請(qǐng)求數(shù)
        long count = requestCounts.values().stream()
            .filter(timestamp -> currentTime - timestamp < TimeUnit.MINUTES.toMillis(1))
            .count();

        if (count >= ALLOWED_REQUESTS_PER_MINUTE) {
            response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
            response.getWriter().write("請(qǐng)求過(guò)于頻繁");
            return false;
        }

        requestCounts.put(clientIp, currentTime);
        return true;
    }
}

?關(guān)鍵對(duì)比與選擇建議?

?方案??適用場(chǎng)景??優(yōu)點(diǎn)??缺點(diǎn)?
Redis + Lua分布式環(huán)境,高精度限流原子性操作,支持分布式,可動(dòng)態(tài)調(diào)整參數(shù)依賴Redis,網(wǎng)絡(luò)開(kāi)銷較大
內(nèi)存計(jì)數(shù)器單機(jī)環(huán)境,簡(jiǎn)單場(chǎng)景無(wú)外部依賴,實(shí)現(xiàn)簡(jiǎn)單不支持分布式,重啟后數(shù)據(jù)丟失

?擴(kuò)展建議?:

  • ?動(dòng)態(tài)配置?:將限流參數(shù)(如DEFAULT_LIMIT)改為從配置中心讀取。
  • ?注解化?:結(jié)合自定義注解(如@RateLimit)實(shí)現(xiàn)更靈活的限流規(guī)則。

兩種方案均能有效實(shí)現(xiàn)接口限流,根據(jù)項(xiàng)目需求選擇即可。

到此這篇關(guān)于SpringBoot通過(guò)攔截器實(shí)現(xiàn)接口限流的兩種方案的文章就介紹到這了,更多相關(guān)SpringBoot攔截器接口限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springcloud中Feign傳遞參數(shù)的過(guò)程解析

    Springcloud中Feign傳遞參數(shù)的過(guò)程解析

    這篇文章主要介紹了Springcloud中Feign傳遞參數(shù)的過(guò)程,單個(gè)參數(shù)的傳值有兩種方式,第一種使用@RequestParam/@PathVariable進(jìn)行傳值,傳遞多個(gè)參數(shù):多個(gè)參數(shù)的傳值可以使用多個(gè)@RequestParam來(lái)進(jìn)行傳參,需要的朋友可以參考下
    2023-09-09
  • SpringSecurity實(shí)現(xiàn)前后端分離登錄token認(rèn)證詳解

    SpringSecurity實(shí)現(xiàn)前后端分離登錄token認(rèn)證詳解

    目前市面上比較流行的權(quán)限框架主要實(shí)Shiro和Spring Security,這兩個(gè)框架各自側(cè)重點(diǎn)不同,各有各的優(yōu)劣,本文將給大家詳細(xì)介紹SpringSecurity如何實(shí)現(xiàn)前后端分離登錄token認(rèn)證
    2023-06-06
  • struts中動(dòng)態(tài)方法調(diào)用使用通配符

    struts中動(dòng)態(tài)方法調(diào)用使用通配符

    這篇文章主要介紹了struts中動(dòng)態(tài)方法調(diào)用使用通配符的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-09-09
  • 解決SpringBoot多模塊發(fā)布時(shí)99%的問(wèn)題

    解決SpringBoot多模塊發(fā)布時(shí)99%的問(wèn)題

    本文歸納了以下 8 個(gè)原則和發(fā)布時(shí)經(jīng)常出現(xiàn)的 4 個(gè)問(wèn)題的解決方案,掌握了這些原則和解決方案,幾乎可以解決絕大數(shù)SpringBoot發(fā)布問(wèn)題
    2019-07-07
  • Java利用Spire.Doc實(shí)現(xiàn)XML轉(zhuǎn)PDF的實(shí)戰(zhàn)指南

    Java利用Spire.Doc實(shí)現(xiàn)XML轉(zhuǎn)PDF的實(shí)戰(zhàn)指南

    本文介紹了使用Spire.DocforJava將XML轉(zhuǎn)換為PDF的過(guò)程,首先說(shuō)明了XML和PDF的應(yīng)用場(chǎng)景,然后通過(guò)Maven引入依賴,核心代碼展示了加載XML并轉(zhuǎn)換為PDF的方法,最后討論了進(jìn)階設(shè)置、注意事項(xiàng)及常見(jiàn)問(wèn)題,幫助開(kāi)發(fā)者更好地完成轉(zhuǎn)換任務(wù),需要的朋友可以參考下
    2026-04-04
  • Java設(shè)計(jì)模式之責(zé)任鏈模式

    Java設(shè)計(jì)模式之責(zé)任鏈模式

    這篇文章介紹了Java設(shè)計(jì)模式之責(zé)任鏈模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • SpringBoot+隨機(jī)鹽值+雙重MD5實(shí)現(xiàn)加密登錄

    SpringBoot+隨機(jī)鹽值+雙重MD5實(shí)現(xiàn)加密登錄

    數(shù)據(jù)加密在很多項(xiàng)目上都可以用到,大部分都會(huì)采用MD5進(jìn)行加密,本文主要介紹了SpringBoot+隨機(jī)鹽值+雙重MD5實(shí)現(xiàn)加密登錄,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • SpringBoot-JPA刪除不成功,只執(zhí)行了查詢語(yǔ)句問(wèn)題

    SpringBoot-JPA刪除不成功,只執(zhí)行了查詢語(yǔ)句問(wèn)題

    這篇文章主要介紹了SpringBoot-JPA刪除不成功,只執(zhí)行了查詢語(yǔ)句問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • java監(jiān)聽(tīng)器實(shí)現(xiàn)在線人數(shù)統(tǒng)計(jì)

    java監(jiān)聽(tīng)器實(shí)現(xiàn)在線人數(shù)統(tǒng)計(jì)

    這篇文章主要為大家詳細(xì)介紹了java監(jiān)聽(tīng)器實(shí)現(xiàn)在線人數(shù)統(tǒng)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Java實(shí)現(xiàn)HTML轉(zhuǎn)Word的完整指南

    Java實(shí)現(xiàn)HTML轉(zhuǎn)Word的完整指南

    在Java應(yīng)用程序中處理文檔轉(zhuǎn)換時(shí),經(jīng)常需要將HTML內(nèi)容精準(zhǔn)導(dǎo)出為格式規(guī)范的Word文檔,通過(guò)Spire.Doc for Java庫(kù),開(kāi)發(fā)者可以輕松實(shí)現(xiàn)HTML到Word的高保真轉(zhuǎn)換,所以本文給大家介紹了Java實(shí)現(xiàn)HTML轉(zhuǎn)Word的完整指南,需要的朋友可以參考下
    2025-09-09

最新評(píng)論

桃源县| 忻城县| 宁明县| 安义县| 屏东市| 崇阳县| 新闻| 北碚区| 报价| 和田市| 崇文区| 黄骅市| 桓台县| 西峡县| 泽库县| 炉霍县| 化州市| 唐海县| 莱芜市| 东台市| 通山县| 四平市| 泽州县| 上思县| 潼关县| 石河子市| 东乡县| 阿荣旗| 屏山县| 东安县| 武冈市| 定南县| 阿城市| 项城市| 绥棱县| 阳朔县| 保康县| 濮阳县| 芮城县| 闽清县| 云安县|