欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)限流接口的示例詳解

 更新時(shí)間:2023年12月21日 10:01:17   作者:myprince003  
限流是對(duì)某一時(shí)間窗口內(nèi)的請(qǐng)求數(shù)進(jìn)行限制,保持系統(tǒng)的可用性和穩(wěn)定性,防止因流量暴增而導(dǎo)致的系統(tǒng)運(yùn)行緩慢或宕機(jī),本文主要來(lái)和大家聊聊如何使用java實(shí)現(xiàn)限流接口,感興趣的可以了解下

一、限流

為什么要進(jìn)行限流?

1.瞬時(shí)流量過(guò)高,服務(wù)被壓垮?

2.惡意用戶高頻光顧,導(dǎo)致服務(wù)器宕機(jī)?

3.消息消費(fèi)過(guò)快,導(dǎo)致數(shù)據(jù)庫(kù)壓力過(guò)大,性能下降甚至崩潰?

……

什么是限流?

限流是對(duì)某一時(shí)間窗口內(nèi)的請(qǐng)求數(shù)進(jìn)行限制,保持系統(tǒng)的可用性和穩(wěn)定性,防止因流量暴增而導(dǎo)致的系統(tǒng)運(yùn)行緩慢或宕機(jī)。
在高并發(fā)系統(tǒng)中,出于系統(tǒng)保護(hù)角度考慮,通常會(huì)對(duì)流量進(jìn)行限流。
在分布式系統(tǒng)中,高并發(fā)場(chǎng)景下,為了防止系統(tǒng)因突然的流量激增而導(dǎo)致的崩潰,同時(shí)保證服務(wù)的高可用性和穩(wěn)定性,限流是最常用的手段。

有哪些限流算法?

常見(jiàn)的四種限流算法,分別是:固定窗口算法、滑動(dòng)窗口算法、漏桶算法、令牌桶算法。

二、限流算法

固定窗口

實(shí)現(xiàn)原理

固定窗口又稱固定窗口(又稱計(jì)數(shù)器算法,F(xiàn)ixed Window)限流算法,是最簡(jiǎn)單的限流算法。

實(shí)現(xiàn)原理:在指定周期內(nèi)累加訪問(wèn)次數(shù),當(dāng)訪問(wèn)次數(shù)達(dá)到設(shè)定的閾值時(shí),觸發(fā)限流策略,當(dāng)進(jìn)入下一個(gè)時(shí)間周期時(shí)進(jìn)行訪問(wèn)次數(shù)的清零。如圖所示,我們要求3秒內(nèi)的請(qǐng)求不要超過(guò)150次:

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

public class FixedWindowRateLimiter {
    Logger logger = LoggerFactory.getLogger(FixedWindowRateLimiter.class);
    //時(shí)間窗口大小,單位毫秒
    long windowSize;
    //允許通過(guò)的請(qǐng)求數(shù)
    int maxRequestCount;
    //當(dāng)前窗口通過(guò)的請(qǐng)求數(shù)
    AtomicInteger counter = new AtomicInteger(0);
    //窗口右邊界
    long windowBorder;
    public FixedWindowRateLimiter(long windowSize, int maxRequestCount) {
        this.windowSize = windowSize;
        this.maxRequestCount = maxRequestCount;
        this.windowBorder = System.currentTimeMillis() + windowSize;
    }
    public synchronized boolean tryAcquire() {
        long currentTime = System.currentTimeMillis();
        if (windowBorder < currentTime) {
            logger.info("window reset");
            do {
                windowBorder += windowSize;
            } while (windowBorder < currentTime);
            counter = new AtomicInteger(0);
        }

        if (counter.intValue() < maxRequestCount) {
            counter.incrementAndGet();
            logger.info("tryAcquire success");
            return true;
        } else {
            logger.info("tryAcquire fail");
            return false;
        }
    }
}

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,容易理解

缺點(diǎn):

1.限流不夠平滑。例如:限流是每秒3個(gè),在第一毫秒發(fā)送了3個(gè)請(qǐng)求,達(dá)到限流,窗口剩余時(shí)間的請(qǐng)求都將會(huì)被拒絕,體驗(yàn)不好。

2.無(wú)法處理窗口邊界問(wèn)題。因?yàn)槭窃谀硞€(gè)時(shí)間窗口內(nèi)進(jìn)行流量控制,所以可能會(huì)出現(xiàn)窗口邊界效應(yīng),即在時(shí)間窗口的邊界處可能會(huì)有大量的請(qǐng)求被允許通過(guò),從而導(dǎo)致突發(fā)流量。即:如果第2到3秒內(nèi)產(chǎn)生了150次請(qǐng)求,而第3到4秒內(nèi)產(chǎn)生了150次請(qǐng)求,那么其實(shí)在第2秒到第4秒這兩秒內(nèi),就已經(jīng)發(fā)生了300次請(qǐng)求了,遠(yuǎn)遠(yuǎn)大于我們要求的3秒內(nèi)的請(qǐng)求不要超過(guò)150次這個(gè)限制,如下圖所示:

滑動(dòng)窗口

實(shí)現(xiàn)原理

滑動(dòng)窗口為固定窗口的改良版,解決了固定窗口在窗口切換時(shí)會(huì)受到兩倍于閾值數(shù)量的請(qǐng)求。在滑動(dòng)窗口算法中,窗口的起止時(shí)間是動(dòng)態(tài)的,窗口的大小固定。這種算法能夠較好地處理窗口邊界問(wèn)題,但是實(shí)現(xiàn)相對(duì)復(fù)雜,需要記錄每個(gè)請(qǐng)求的時(shí)間戳。

實(shí)現(xiàn)原理:滑動(dòng)窗口在固定窗口的基礎(chǔ)上,將時(shí)間窗口進(jìn)行了更精細(xì)的分片,將一個(gè)窗口分為若干個(gè)等份的小窗口,每次僅滑動(dòng)一小塊的時(shí)間。每個(gè)小窗口對(duì)應(yīng)不同的時(shí)間點(diǎn),擁有獨(dú)立的計(jì)數(shù)器,當(dāng)請(qǐng)求的時(shí)間點(diǎn)大于當(dāng)前窗口的最大時(shí)間點(diǎn)時(shí),則將窗口向前平移一個(gè)小窗口(將第一個(gè)小窗口的數(shù)據(jù)舍棄,第二個(gè)小窗口變成第一個(gè)小窗口,當(dāng)前請(qǐng)求放在最后一個(gè)小窗口),整個(gè)窗口的所有請(qǐng)求數(shù)相加不能大于閾值。其中,Sentinel就是采用滑動(dòng)窗口算法來(lái)實(shí)現(xiàn)限流的。如圖所示:

核心步驟:

1.把3秒鐘劃分為3個(gè)小窗,每個(gè)小窗限制請(qǐng)求不能超過(guò)50秒。

2.比如我們?cè)O(shè)置,3秒內(nèi)不能超過(guò)150個(gè)請(qǐng)求,那么這個(gè)窗口就可以容納3個(gè)小窗,并且隨著時(shí)間推移,往前滑動(dòng)。每次請(qǐng)求過(guò)來(lái)后,都要統(tǒng)計(jì)滑動(dòng)窗口內(nèi)所有小窗的請(qǐng)求總量。

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

public class SlidingWindowRateLimiter {
    Logger logger = LoggerFactory.getLogger(FixedWindowRateLimiter.class);
    //時(shí)間窗口大小,單位毫秒
    long windowSize;
    //分片窗口數(shù)
    int shardNum;
    //允許通過(guò)的請(qǐng)求數(shù)
    int maxRequestCount;
    //各個(gè)窗口內(nèi)請(qǐng)求計(jì)數(shù)
    int[] shardRequestCount;
    //請(qǐng)求總數(shù)
    int totalCount;
    //當(dāng)前窗口下標(biāo)
    int shardId;
    //每個(gè)小窗口大小,毫秒
    long tinyWindowSize;
    //窗口右邊界
    long windowBorder;

    public SlidingWindowRateLimiter(long windowSize, int shardNum, int maxRequestCount) {
        this.windowSize = windowSize;
        this.shardNum = shardNum;
        this.maxRequestCount = maxRequestCount;
        this.shardRequestCount = new int[shardNum];
        this.tinyWindowSize = windowSize / shardNum;
        this.windowBorder = System.currentTimeMillis();
    }
    public synchronized boolean tryAcquire() {
        long currentTime = System.currentTimeMillis();
        if (windowBorder < currentTime) {
            logger.info("window reset");
            do {
                shardId = (++shardId) % shardNum;
                totalCount -= shardRequestCount[shardId];
                shardRequestCount[shardId] = 0;
                windowBorder += tinyWindowSize;
            } while (windowBorder < currentTime);
        }

        if (totalCount < maxRequestCount) {
            logger.info("tryAcquire success:{}", shardId);
            shardRequestCount[shardId]++;
            totalCount++;
            return true;
        } else {
            logger.info("tryAcquire fail");
            return false;
        }
    }
}

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):解決了固定窗口算法的窗口邊界問(wèn)題,避免突發(fā)流量壓垮服務(wù)器。

缺點(diǎn):還是存在限流不夠平滑的問(wèn)題。例如:限流是每秒3個(gè),在第一毫秒發(fā)送了3個(gè)請(qǐng)求,達(dá)到限流,剩余窗口時(shí)間的請(qǐng)求都將會(huì)被拒絕,體驗(yàn)不好。

漏桶算法

實(shí)現(xiàn)原理

漏桶限流算法是一種常用的流量整形(Traffic Shaping)和流量控制(Traffic Policing)的算法,它可以有效地控制數(shù)據(jù)的傳輸速率以及防止網(wǎng)絡(luò)擁塞。

主要的作用:

a.控制數(shù)據(jù)注入網(wǎng)絡(luò)的速度。

b.平滑網(wǎng)絡(luò)上的突發(fā)流量

實(shí)現(xiàn)原理:

漏桶是一個(gè)很形象的比喻,外部請(qǐng)求就像是水一樣不斷注入水桶中,而水桶已經(jīng)設(shè)置好了最大出水速率,漏桶會(huì)以這個(gè)速率勻速放行請(qǐng)求,而當(dāng)水超過(guò)桶的最大容量后則被丟棄。不管上面的水流速度有多塊,漏桶水滴的流出速度始終保持不變。消息中間件就采用的漏桶限流的思想。如圖所示:

核心步驟:

a.一個(gè)固定容量的漏桶,按照固定速率出水(處理請(qǐng)求);

b.當(dāng)流入水(請(qǐng)求數(shù)量)的速度過(guò)大會(huì)直接溢出(請(qǐng)求數(shù)量超過(guò)限制則直接拒絕)。

c.桶里的水(請(qǐng)求)不夠則無(wú)法出水(桶內(nèi)沒(méi)有請(qǐng)求則不處理)。

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

public class LeakyBucketRateLimiter {
    Logger logger = LoggerFactory.getLogger(LeakyBucketRateLimiter.class);
    //桶的容量
    int capacity;
    //桶中現(xiàn)存水量
    AtomicInteger water = new AtomicInteger();
    //開(kāi)始漏水時(shí)間
    long leakTimestamp;
    //水流出的速率,即每秒允許通過(guò)的請(qǐng)求數(shù)
    int leakRate;

    public LeakyBucketRateLimiter(int capacity, int leakRate) {
        this.capacity = capacity;
        this.leakRate = leakRate;
    }

    public synchronized boolean tryAcquire() {
        //桶中沒(méi)有水, 重新開(kāi)始計(jì)算
        if (water.get() == 0) {
            logger.info("start leaking");
            leakTimestamp = System.currentTimeMillis();
            water.incrementAndGet();
            return water.get() < capacity;
        }
        //先漏水,計(jì)算剩余水量
        long currentTime = System.currentTimeMillis();
        int leakedWater = (int) ((currentTime - leakTimestamp) / 1000 * leakRate);
        logger.info("lastTime:{}, currentTime:{}. LeakedWater:{}", leakTimestamp, currentTime, leakedWater);
        //可能時(shí)間不足,則先不漏水
        if (leakedWater != 0) {
            int leftWater = water.get() - leakedWater;
            //可能水已漏光。設(shè)為0
            water.set(Math.max(0, leftWater));
            leakTimestamp = System.currentTimeMillis();
        }
        logger.info("剩余容量:{}", capacity - water.get());
        if (water.get() < capacity) {
            logger.info("tryAcquire sucess");
            water.incrementAndGet();
            return true;
        } else {
            logger.info("tryAcquire fail");
            return false;
        }
    }
}

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1.平滑流量。由于漏桶算法以固定的速率處理請(qǐng)求,可以有效地平滑和整形流量,避免流量的突發(fā)和波動(dòng)(類似于消息隊(duì)列的削峰填谷的作用)。

2.防止過(guò)載。當(dāng)流入的請(qǐng)求超過(guò)桶的容量時(shí),可以直接丟棄請(qǐng)求,防止系統(tǒng)過(guò)載。

缺點(diǎn):

1.無(wú)法處理突發(fā)流量:由于漏桶的出口速度是固定的,無(wú)法處理突發(fā)流量。例如,即使在流量較小的時(shí)候,也無(wú)法以更快的速度處理請(qǐng)求。

2.可能會(huì)丟失數(shù)據(jù):如果入口流量過(guò)大,超過(guò)了桶的容量,那么就需要丟棄部分請(qǐng)求。在一些不能接受丟失請(qǐng)求的場(chǎng)景中,這可能是一個(gè)問(wèn)題。

3.不適合速率變化大的場(chǎng)景:如果速率變化大,或者需要?jiǎng)討B(tài)調(diào)整速率,那么漏桶算法就無(wú)法滿足需求。

4.資源利用率:不管當(dāng)前系統(tǒng)的負(fù)載壓力如何,所有請(qǐng)求都得進(jìn)行排隊(duì),即使此時(shí)服務(wù)器的負(fù)載處于相對(duì)空閑的狀態(tài),這樣會(huì)造成系統(tǒng)資源的浪費(fèi)。

由于漏桶的缺陷比較明顯,所以在實(shí)際業(yè)務(wù)場(chǎng)景中,使用的比較少。

令牌算法

實(shí)現(xiàn)原理

令牌桶算法是基于漏桶算法的一種改進(jìn),主要在于令牌桶算法能夠在限制服務(wù)調(diào)用的平均速率的同時(shí),還能夠允許一定程度內(nèi)的突發(fā)調(diào)用。

實(shí)現(xiàn)原理:

1.系統(tǒng)以固定的速率向桶中添加令牌;

2.當(dāng)有請(qǐng)求到來(lái)時(shí),會(huì)嘗試從桶中移除一個(gè)令牌,如果桶中有足夠的令牌,則請(qǐng)求可以被處理或數(shù)據(jù)包可以被發(fā)送;

3.如果桶中沒(méi)有令牌,那么請(qǐng)求將被拒絕;

4.桶中的令牌數(shù)不能超過(guò)桶的容量,如果新生成的令牌超過(guò)了桶的容量,那么新的令牌會(huì)被丟棄。

5.令牌桶算法的一個(gè)重要特性是,它能夠應(yīng)對(duì)突發(fā)流量。當(dāng)桶中有足夠的令牌時(shí),可以一次性處理多個(gè)請(qǐng)求,這對(duì)于需要處理突發(fā)流量的應(yīng)用場(chǎng)景非常有用。但是又不會(huì)無(wú)限制的增加處理速率導(dǎo)致壓垮服務(wù)器,因?yàn)橥皟?nèi)令牌數(shù)量是有限制的。

如圖所示:

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

Guava中的RateLimiter就是基于令牌桶實(shí)現(xiàn)的,可以直接拿來(lái)使用。

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

1.可以處理突發(fā)流量:令牌桶算法可以處理突發(fā)流量。當(dāng)桶滿時(shí),能夠以最大速度處理請(qǐng)求。這對(duì)于需要處理突發(fā)流量的應(yīng)用場(chǎng)景非常有用。

2.限制平均速率:在長(zhǎng)期運(yùn)行中,數(shù)據(jù)的傳輸率會(huì)被限制在預(yù)定義的平均速率(即生成令牌的速率)。

3.靈活性:與漏桶算法相比,令牌桶算法提供了更大的靈活性。例如,可以動(dòng)態(tài)地調(diào)整生成令牌的速率。

缺點(diǎn):

1.可能導(dǎo)致過(guò)載:如果令牌產(chǎn)生的速度過(guò)快,可能會(huì)導(dǎo)致大量的突發(fā)流量,這可能會(huì)使網(wǎng)絡(luò)或服務(wù)過(guò)載。

2.需要存儲(chǔ)空間:令牌桶需要一定的存儲(chǔ)空間來(lái)保存令牌,可能會(huì)導(dǎo)致內(nèi)存資源的浪費(fèi)。

3.實(shí)現(xiàn)稍復(fù)雜:相比于計(jì)數(shù)器算法,令牌桶算法的實(shí)現(xiàn)稍微復(fù)雜一些。

三、應(yīng)用實(shí)踐

Guava中的RateLimiter就是基于令牌桶實(shí)現(xiàn)的,可以直接拿來(lái)使用。所有整個(gè)實(shí)踐是基于Guava的應(yīng)用。

引入依賴

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

API直接使用

固定產(chǎn)生令牌

@Test
public void acquireTest() {
    //每秒固定生成5個(gè)令牌
    RateLimiter rateLimiter = RateLimiter.create(5);
    for (int i = 0; i < 10; i++) {
        double time = rateLimiter.acquire();
        logger.info("等待時(shí)間:{}s", time);
    }
}

結(jié)果:

可以看到,每200ms左右產(chǎn)生一個(gè)令牌并放行請(qǐng)求,也就是1秒放行5個(gè)請(qǐng)求,使用RateLimiter能夠很好的實(shí)現(xiàn)單機(jī)的限流。

同時(shí)產(chǎn)生多個(gè)令牌

那么再回到我們前面提到的突發(fā)流量情況,令牌桶是怎么解決的呢?RateLimiter中引入了一個(gè)預(yù)消費(fèi)的概念。

申請(qǐng)令牌的數(shù)量不同不會(huì)影響這個(gè)申請(qǐng)令牌這個(gè)動(dòng)作本身的響應(yīng)時(shí)間,acquire(1)和acquire(1000)這兩個(gè)請(qǐng)求會(huì)消耗同樣的時(shí)間返回結(jié)果,但是會(huì)影響下一個(gè)請(qǐng)求的響應(yīng)時(shí)間。

如果一個(gè)消耗大量令牌的任務(wù)到達(dá)空閑的RateLimiter,會(huì)被立即批準(zhǔn)執(zhí)行,但是當(dāng)下一個(gè)請(qǐng)求進(jìn)來(lái)時(shí),將會(huì)額外等待一段時(shí)間,用來(lái)支付前一個(gè)請(qǐng)求的時(shí)間成本。

至于為什么要這么做,通過(guò)舉例來(lái)引申一下。當(dāng)一個(gè)系統(tǒng)處于空閑狀態(tài)時(shí),突然來(lái)了1個(gè)需要消耗100個(gè)令牌的任務(wù),那么白白等待100秒是毫無(wú)意義的浪費(fèi)資源行為,那么可以先允許它執(zhí)行,并對(duì)后續(xù)請(qǐng)求進(jìn)行限流時(shí)間上的延長(zhǎng),以此來(lái)達(dá)到一個(gè)應(yīng)對(duì)突發(fā)流量的效果。

  @Test
    public void acquireSmoothly() {
        RateLimiter rateLimiter = RateLimiter.create(5, 3, TimeUnit.SECONDS);
        long startTimeStamp = System.currentTimeMillis();
        for (int i = 0; i < 15; i++) {
            double time = rateLimiter.acquire();
            logger.info("等待時(shí)間:{}s, 總時(shí)間:{}ms", time, System.currentTimeMillis() - startTimeStamp);
        }
    }

結(jié)果:

可以看到,令牌發(fā)放時(shí)間從最開(kāi)始的500ms多逐漸縮短,在3秒后達(dá)到了200ms左右的勻速發(fā)放。

總的來(lái)說(shuō),基于令牌桶實(shí)現(xiàn)的RateLimiter功能還是非常強(qiáng)大的,在限流的基礎(chǔ)上還可以把請(qǐng)求平均分散在各個(gè)時(shí)間段內(nèi),因此在單機(jī)情況下它是使用比較廣泛的限流組件。

AOP切面

第一步:創(chuàng)建注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface Limit {
    // 資源主鍵
    String key() default "";
    //最多訪問(wèn)次數(shù),代表請(qǐng)求總數(shù)量
    double permitsPerSeconds();
    // 時(shí)間:即timeout時(shí)間內(nèi),只允許有permitsPerSeconds個(gè)請(qǐng)求總數(shù)量訪問(wèn),超過(guò)的將被限制不能訪問(wèn)
    long timeout();
    //時(shí)間類型
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;

    //提示信息
    String msg() default "系統(tǒng)繁忙,請(qǐng)稍后重試";
}

第二步:AOP切面實(shí)現(xiàn)

@Aspect
@Component
public class LimitAspect {
    Logger logger = LoggerFactory.getLogger(LimitAspect.class);
    private final Map<String, RateLimiter> limitMap = Maps.newConcurrentMap();

???@Around("@annotation(com.alibaba.xxx.xxx.annotation.Limit)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //拿limit的注解
        Limit limit = method.getAnnotation(Limit.class);
        if (limit != null) {
            // key作用:不同的接口,不同的流量控制
            String key = limit.key();
            RateLimiter rateLimiter;
            //驗(yàn)證緩存是否有命中key
            if (!limitMap.containsKey(key)) {
                //創(chuàng)建令牌桶
                rateLimiter = RateLimiter.create(limit.permitsPerSeconds());
                limitMap.put(key, rateLimiter);
                logger.info("新建了令牌桶={},容量={}", key, limit.permitsPerSeconds());
            }
            rateLimiter = limitMap.get(key);
            //拿令牌
            boolean acquire = rateLimiter.tryAcquire(limit.timeout(), limit.timeUnit());
            //拿不到令牌,直接返回異常信息
            if (!acquire) {
                logger.debug("令牌桶={},獲取令牌失敗", key);
                throw new RuntimeException(limit.msg());
            }
        }
        return joinPoint.proceed();
    }
}

第三步:應(yīng)用

@Limit(key = "query",
permitsPerSeconds = 1,
timeout = 1,
msg = "觸發(fā)接口限流,請(qǐng)重試")

第四步:使用位置詳解

若是放在http的mapping接口上,返回如下

{
    "timestamp": "2023-12-07 11:21:47",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/table/query"
}

若是放在service服務(wù)的接口上,返回如下

{
    "code": -1,
    "message": "觸發(fā)接口限流,請(qǐng)重試",
    "data": "fail"
}

四、總結(jié)

本文介紹的實(shí)現(xiàn)方式屬于應(yīng)用級(jí)限制,應(yīng)用級(jí)限流方式只是單應(yīng)用內(nèi)的請(qǐng)求限流,不能進(jìn)行全局限流。假設(shè)將應(yīng)用部署到多臺(tái)機(jī)器,我們需要分布式限流和接入層限流來(lái)解決這個(gè)問(wèn)題。

總的來(lái)說(shuō),要保證系統(tǒng)的抗壓能力,限流是一個(gè)必不可少的環(huán)節(jié),雖然可能會(huì)造成某些用戶的請(qǐng)求被丟棄,但相比于突發(fā)流量造成的系統(tǒng)宕機(jī)來(lái)說(shuō),這些損失一般都在可以接受的范圍之內(nèi)。前面也說(shuō)過(guò),限流可以結(jié)合熔斷、降級(jí)一起使用,多管齊下,保證服務(wù)的可用性與健壯性。

以上就是Java實(shí)現(xiàn)限流接口的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Java限流接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用java實(shí)現(xiàn)銀行家算法

    使用java實(shí)現(xiàn)銀行家算法

    這篇文章主要為大家詳細(xì)介紹了如何使用java實(shí)現(xiàn)銀行家算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • 淺談java Iterator.remove()方法的用法(詳解)

    淺談java Iterator.remove()方法的用法(詳解)

    下面小編就為大家?guī)?lái)一篇淺談java Iterator.remove()方法的用法(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • java實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    java實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • SpringBoot+MinIO+KKFileView實(shí)現(xiàn)文件預(yù)覽功能

    SpringBoot+MinIO+KKFileView實(shí)現(xiàn)文件預(yù)覽功能

    本文主要介紹了使用SpringBoot、MinIO和KKFileView實(shí)現(xiàn)文件上傳和在線預(yù)覽功能,通過(guò)配置MinIO存儲(chǔ)文件,并使用KKFileView生成預(yù)覽鏈接,感興趣的可以了解一下
    2024-11-11
  • 簡(jiǎn)單了解Java synchronized關(guān)鍵字同步

    簡(jiǎn)單了解Java synchronized關(guān)鍵字同步

    這篇文章主要介紹了簡(jiǎn)單了解Java synchronized關(guān)鍵字同步,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Tomcat ClassLoader打破雙親委派源碼解析

    Tomcat ClassLoader打破雙親委派源碼解析

    這篇文章主要為大家介紹了Tomcat ClassLoader打破雙親委派源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Java的基礎(chǔ)語(yǔ)法學(xué)習(xí)筆記

    Java的基礎(chǔ)語(yǔ)法學(xué)習(xí)筆記

    這里為大家整理了Java的基礎(chǔ)語(yǔ)法學(xué)習(xí)筆記,包括關(guān)鍵詞、運(yùn)算符與基本的流程控制語(yǔ)句寫(xiě)法等,需要的朋友可以參考下
    2016-05-05
  • spring profile 多環(huán)境配置管理詳解

    spring profile 多環(huán)境配置管理詳解

    這篇文章主要介紹了 spring profile 多環(huán)境配置管理詳解的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • 解決spring-data-jpa 事物中修改屬性自動(dòng)更新update問(wèn)題

    解決spring-data-jpa 事物中修改屬性自動(dòng)更新update問(wèn)題

    這篇文章主要介紹了解決spring-data-jpa 事物中修改屬性自動(dòng)更新update問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家
    2021-08-08
  • SpringBoot通過(guò)Filter實(shí)現(xiàn)整個(gè)項(xiàng)目接口的SQL注入攔截詳解

    SpringBoot通過(guò)Filter實(shí)現(xiàn)整個(gè)項(xiàng)目接口的SQL注入攔截詳解

    這篇文章主要介紹了SpringBoot通過(guò)Filter實(shí)現(xiàn)整個(gè)項(xiàng)目接口的SQL注入攔截詳解,SQL注入是比較常見(jiàn)的網(wǎng)絡(luò)攻擊方式之一,在客戶端在向服務(wù)器發(fā)送請(qǐng)求的時(shí)候,sql命令通過(guò)表單提交或者url字符串拼接傳遞到后臺(tái)持久層,最終達(dá)到欺騙服務(wù)器執(zhí)行惡意的SQL命令,需要的朋友可以參考下
    2023-12-12

最新評(píng)論