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

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

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

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

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

?核心邏輯?

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

?代碼實現(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秒過期

    @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. 注冊攔截器

@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)存計數(shù)器的單機(jī)限流?

?核心邏輯?

  1. ?攔截器?:使用ConcurrentHashMap存儲IP和訪問時間戳。
  2. ?滑動窗口?:統(tǒng)計1分鐘內(nèi)的請求數(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();

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

        // 統(tǒng)計當(dā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("請求過于頻繁");
            return false;
        }

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

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

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

?擴(kuò)展建議?:

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

    解決SpringBoot多模塊發(fā)布時99%的問題

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評論

类乌齐县| 于都县| 迭部县| 饶阳县| 若尔盖县| 兴隆县| 通河县| 宜阳县| 错那县| 龙川县| 来安县| 普宁市| 宣恩县| 岑巩县| 定陶县| 侯马市| 托里县| 宣汉县| 南丰县| 扎赉特旗| 弋阳县| 临漳县| 武威市| 大邑县| 江源县| 会理县| 镇赉县| 波密县| 安图县| 吉木乃县| 孟连| 广汉市| 保德县| 咸丰县| 伊通| 纳雍县| 读书| 新昌县| 麻栗坡县| 伊金霍洛旗| 西平县|