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

SpringBoot 接口防護(hù)(防重提交 + 限流)

 更新時(shí)間:2026年03月25日 10:29:10   作者:BigGGGuardian  
Guardian 是一個(gè)輕量級(jí) Spring Boot API 請(qǐng)求層防護(hù)框架,提供防重復(fù)提交和接口限流兩大能力,本文就來(lái)詳細(xì)的介紹一下SpringBoot 接口防護(hù)(防重提交 + 限流),感興趣的可以了解一下

前言

事情是這樣的,前段時(shí)間在公司項(xiàng)目里又寫(xiě)了一遍防重復(fù)提交的邏輯——Redis 加鎖、拼 Key、設(shè)過(guò)期時(shí)間、處理異常釋放鎖……寫(xiě)到一半我就煩了,這套東西每個(gè)項(xiàng)目都要來(lái)一遍,而且每次寫(xiě)法還不太一樣,維護(hù)起來(lái)頭大。

限流也是,要么上 Sentinel 搞一套,要么自己寫(xiě)個(gè)攔截器糊一個(gè),代碼散得到處都是。

想了想,干脆自己封一個(gè) Starter。搞著搞著就把防重復(fù)提交和接口限流都做了,打包發(fā)到 Maven Central 開(kāi)源了。

項(xiàng)目叫 Guardian,一個(gè)輕量級(jí)的 Spring Boot API 請(qǐng)求層防護(hù)框架,目前 v1.3.0。兩個(gè)功能完全獨(dú)立,用哪個(gè)引哪個(gè),互不依賴。

項(xiàng)目地址(源碼 + 示例 + 文檔全在里面):

一、防重復(fù)提交

先看效果

三步搞定:

第一步,引依賴:

<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-repeat-submit-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>

第二步,加注解:

@PostMapping("/submit")
@RepeatSubmit(interval = 10, message = "訂單正在處理,請(qǐng)勿重復(fù)提交")
public Result submitOrder(@RequestBody OrderDTO order) {
    return orderService.submit(order);
}

第三步,沒(méi)了。啟動(dòng)項(xiàng)目就生效了。

10 秒內(nèi)同一個(gè)用戶、同一個(gè)接口、同樣的請(qǐng)求參數(shù),第二次請(qǐng)求會(huì)被直接攔截。

為什么不直接用 Redis 加個(gè)鎖?

你肯定想說(shuō):"這不就是 Redis setnx 嘛,我自己寫(xiě)也行。"

確實(shí)能寫(xiě),但你想想實(shí)際項(xiàng)目里會(huì)遇到的問(wèn)題:

1. Key 怎么拼?

userId + url 夠不夠?如果同一個(gè)用戶對(duì)同一個(gè)接口傳了不同的參數(shù)呢?比如下單接口,買(mǎi)商品 A 和買(mǎi)商品 B 應(yīng)該算兩次不同的請(qǐng)求,不能攔截。

所以防重 Key 要把請(qǐng)求參數(shù)也算進(jìn)去。但 POST 請(qǐng)求的 body 是個(gè)流,讀了一次就沒(méi)了,你還得處理 HttpServletRequestWrapper 的問(wèn)題。

Guardian 內(nèi)置了 RepeatableRequestFilter,自動(dòng)緩存請(qǐng)求體,Key 生成時(shí)會(huì)把請(qǐng)求參數(shù)做 JSON 序列化 + Base64 編碼拼進(jìn)去。

2. 用戶沒(méi)登錄怎么辦?

很多防重方案直接用 userId 作為 Key 的一部分,但用戶沒(méi)登錄的時(shí)候 userId 是 null,Key 就亂了。

Guardian 的處理是:已登錄用 userId → 沒(méi)登錄用 sessionId → 沒(méi) session 用客戶端 IP。三級(jí)降級(jí),永遠(yuǎn)不會(huì)出現(xiàn) null。

3. 業(yè)務(wù)異常了鎖不釋放怎么辦?

比如用戶提交訂單,業(yè)務(wù)代碼報(bào)了個(gè)異常,但防重鎖已經(jīng)設(shè)了 10 秒。結(jié)果用戶修正數(shù)據(jù)重新提交,被告知"請(qǐng)勿重復(fù)提交"——這體驗(yàn)就很差了。

Guardian 在攔截器的 afterCompletion 里做了處理:如果請(qǐng)求拋了異常,自動(dòng)釋放鎖。正常完成的請(qǐng)求才讓鎖自然過(guò)期。

4. 有些接口不需要防重怎么辦?

全局配了防重之后,健康檢查接口、公開(kāi)查詢接口這些也被攔了。你要么給每個(gè)接口單獨(dú)控制,要么維護(hù)一個(gè)白名單。

Guardian 支持 exclude-urls 白名單,AntPath 通配符匹配,優(yōu)先級(jí)最高。命中直接放行,不走任何防重邏輯。

注解不夠用?試試 YAML 批量配置

單個(gè)接口用注解挺方便,但如果你有 50 個(gè)接口都要配防重,一個(gè)一個(gè)加注解就有點(diǎn)累了。

Guardian 支持在 YAML 里批量配置,用 AntPath 通配符一口氣匹配一批接口:

guardian:
  repeat-submit:
    storage: redis
    key-encrypt: md5
    urls:
      - pattern: /api/order/**
        interval: 10
        key-scope: user
        message: "訂單正在處理,請(qǐng)勿重復(fù)提交"
      - pattern: /api/sms/send
        interval: 60
        key-scope: ip
    exclude-urls:
      - /api/public/**
      - /api/health

幾個(gè)要點(diǎn):

  • YAML 規(guī)則的優(yōu)先級(jí)高于注解,同一個(gè)接口兩邊都配了以 YAML 為準(zhǔn)
  • 白名單(exclude-urls)優(yōu)先級(jí)最高,命中直接放行
  • key-scope 控制防重維度:user(按用戶)、ip(按 IP)、global(全局)

比如短信發(fā)送接口配 key-scope: ip,同一個(gè) IP 60 秒內(nèi)只能發(fā)一次,不管登沒(méi)登錄、哪個(gè)用戶——這比按用戶維度更合理。

攔截了之后怎么響應(yīng)?

這是我糾結(jié)了挺久的一個(gè)設(shè)計(jì)點(diǎn)。

一開(kāi)始只做了拋異常的方式——攔截后拋 RepeatSubmitException,讓業(yè)務(wù)端的全局異常處理器去處理。但后來(lái)想到,有些項(xiàng)目可能就想開(kāi)箱即用,不想為了一個(gè)防重還得寫(xiě)個(gè)異常處理器。

所以做了兩種模式:

guardian:
  repeat-submit:
    response-mode: exception  # 默認(rèn),拋異常
    # response-mode: json     # 直接返回 JSON

exception 模式(默認(rèn)):拋 RepeatSubmitException,你在全局異常處理器里接一下:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(RepeatSubmitException.class)
    public Result handleRepeatSubmit(RepeatSubmitException e) {
        return Result.fail(e.getMessage());
    }
}

json 模式:攔截器直接寫(xiě) JSON 響應(yīng),默認(rèn)格式是 {"code":500,"msg":"...","timestamp":...}。

格式不滿意?注冊(cè)一個(gè) RepeatSubmitResponseHandler Bean 就能覆蓋:

@Bean
public RepeatSubmitResponseHandler repeatSubmitResponseHandler() {
    return (request, response, message) -> {
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JSONUtil.toJsonStr(R.fail(message)));
    };
}

不用 Redis 也能跑

不是每個(gè)項(xiàng)目都有 Redis 的。本地開(kāi)發(fā)環(huán)境、小型單體應(yīng)用,可能就沒(méi)有 Redis。

guardian:
  repeat-submit:
    storage: local  # 用本地緩存

切成 local 就行了,底層用 ConcurrentHashMap 實(shí)現(xiàn),帶定時(shí)過(guò)期清理。當(dāng)然生產(chǎn)環(huán)境還是推薦 Redis,支持分布式。

想看 Redis 存儲(chǔ)和本地存儲(chǔ)的具體實(shí)現(xiàn)?源碼在 guardian-storage-redisRepeatSubmitLocalStorage

關(guān)于 context-path 的坑

這個(gè)坑我自己踩過(guò)。項(xiàng)目配了 server.servlet.context-path: /admin-api,然后 YAML 里配的 URL 規(guī)則死活匹配不上。

排查了一下發(fā)現(xiàn),request.getRequestURI() 返回的是帶 context-path 的完整路徑(比如 /admin-api/order/submit),但 YAML 里配的可能是 /order/submit。

Guardian 的處理是:匹配時(shí)同時(shí)嘗試完整 URI 和去掉 context-path 后的路徑,兩者有一個(gè)匹配上就算命中。所以不管你 YAML 里寫(xiě)的是 /order/submit 還是 /admin-api/order/submit,都能正確匹配。

防重的內(nèi)部流程

簡(jiǎn)單畫(huà)一下請(qǐng)求的處理流程:

請(qǐng)求進(jìn)入
  │
  ▼
RepeatableRequestFilter     ← 緩存請(qǐng)求體,支持重復(fù)讀取
  │
  ▼
RepeatSubmitInterceptor
  ├─ 1. 匹配白名單 → 命中直接放行
  ├─ 2. 匹配 YAML 規(guī)則
  ├─ 3. 檢查 @RepeatSubmit 注解
  │      均未命中 → 放行
  ▼
KeyGenerator                ← 按維度(user/ip/global)生成防重 Key
  │
  ▼
KeyEncrypt                  ← 可選 MD5 加密
  │
  ▼
Storage.tryAcquire()
  ├─ 成功 → 放行,寫(xiě)入存儲(chǔ) + 設(shè)置 TTL
  └─ 失敗 → 根據(jù) response-mode 響應(yīng)
      ├─ exception → 拋 RepeatSubmitException
      └─ json → 直接寫(xiě) JSON 響應(yīng)
  │
  ▼
業(yè)務(wù)執(zhí)行
  ├─ 正常 → Key 自然過(guò)期
  └─ 異常 → afterCompletion 自動(dòng)釋放

二、接口限流

為什么要做限流?

防重復(fù)提交解決的是"同一個(gè)請(qǐng)求短時(shí)間內(nèi)被提交多次"的問(wèn)題,但還有另一類問(wèn)題它管不了:惡意刷接口。

比如有人寫(xiě)個(gè)腳本一秒鐘請(qǐng)求你的搜索接口 1000 次,防重?cái)r不?。ㄒ?yàn)槊看螀?shù)可能不一樣),這時(shí)候就需要限流了。

市面上的限流方案不少,但要么是網(wǎng)關(guān)級(jí)別的(Sentinel、Spring Cloud Gateway),要么得寫(xiě)一堆配置。如果你就是個(gè)普通的 Spring Boot 單體應(yīng)用,想給幾個(gè)接口加個(gè)限流,沒(méi)必要引那么重的東西。

Guardian 的限流就是沖著這個(gè)場(chǎng)景來(lái)的:輕量、注解 + YAML 雙模式、兩種算法可選。

先看效果

<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-rate-limit-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>
// 滑動(dòng)窗口:每秒最多 10 次
@RateLimit(qps = 10)
// 令牌桶:每秒補(bǔ) 5 個(gè)令牌,桶容量 20,允許瞬間突發(fā) 20 次
@RateLimit(qps = 5, capacity = 20, algorithm = RateLimitAlgorithm.TOKEN_BUCKET)

同樣支持 YAML 批量配置:

guardian:
  rate-limit:
    urls:
      - pattern: /api/sms/send
        qps: 1
        rate-limit-scope: ip
      - pattern: /api/seckill/**
        qps: 10
        capacity: 50
        algorithm: token_bucket
        rate-limit-scope: global
    exclude-urls:
      - /api/public/**

和防重一樣,注解 + YAML 雙模式,YAML 優(yōu)先級(jí)高于注解,白名單優(yōu)先級(jí)最高。

滑動(dòng)窗口 vs 令牌桶

這是限流最常用的兩種算法,Guardian 都支持。

滑動(dòng)窗口:統(tǒng)計(jì)時(shí)間窗口內(nèi)的請(qǐng)求次數(shù),超了就拒絕。比如配了 qps=10, window=1s,就是每秒最多 10 次,多了直接打回。

@RateLimit(qps = 10)

特點(diǎn)是嚴(yán)格。窗口內(nèi)絕對(duì)不會(huì)超過(guò)閾值。適合短信發(fā)送、登錄嘗試這種需要精確控制頻率的場(chǎng)景。

令牌桶:桶里裝令牌,按固定速率往里放,請(qǐng)求來(lái)了取一個(gè),桶空了就拒絕。桶滿時(shí)可以一口氣把令牌全用完。

@RateLimit(qps = 5, capacity = 20, algorithm = RateLimitAlgorithm.TOKEN_BUCKET)

這個(gè)配置的意思是:每秒補(bǔ) 5 個(gè)令牌,桶最多攢 20 個(gè)。平時(shí)空閑的時(shí)候令牌慢慢攢,突然來(lái)一波流量,瞬間可以放過(guò) 20 個(gè)請(qǐng)求,打完之后回到每秒 5 個(gè)的穩(wěn)態(tài)。

特點(diǎn)是允許突發(fā)。適合秒殺、搶購(gòu)這種"平時(shí)沒(méi)啥流量,偶爾來(lái)一波高峰"的場(chǎng)景。

舉個(gè)直觀的例子,都是 qps=10,突然來(lái)了 20 個(gè)請(qǐng)求:

滑動(dòng)窗口令牌桶(capacity=20)
第 1-10 個(gè)通過(guò)通過(guò)
第 11-20 個(gè)全部拒絕全部通過(guò)
之后每秒最多 10 個(gè)最多 10 個(gè)

補(bǔ)充速率怎么控制?

令牌桶的補(bǔ)充速率通過(guò) qps 和 window 兩個(gè)參數(shù)控制:

  • qps=10, window=1s → 每秒補(bǔ) 10 個(gè)
  • qps=10, window=1min → 每分鐘補(bǔ) 10 個(gè)(約 6 秒補(bǔ) 1 個(gè))
// 每分鐘補(bǔ) 10 個(gè)令牌,桶容量 10
@RateLimit(qps = 10, window = 1, windowUnit = TimeUnit.MINUTES,
        capacity = 10, algorithm = RateLimitAlgorithm.TOKEN_BUCKET)

這樣就能實(shí)現(xiàn)慢速補(bǔ)充的場(chǎng)景。

限流維度

和防重一樣,限流也支持三種維度:

維度效果典型場(chǎng)景
GLOBAL(默認(rèn))整個(gè)接口共用一個(gè)計(jì)數(shù)器全站搜索接口
IP每個(gè) IP 獨(dú)立計(jì)數(shù)短信發(fā)送、驗(yàn)證碼
USER每個(gè)用戶獨(dú)立計(jì)數(shù)用戶操作頻率限制
@RateLimit(qps = 1, rateLimitScope = RateLimitKeyScope.IP, message = "短信發(fā)送過(guò)于頻繁")

限流的響應(yīng)處理

和防重一樣,兩種模式:

guardian:
  rate-limit:
    response-mode: exception  # 默認(rèn),拋 RateLimitException
    # response-mode: json     # 直接返回 JSON

也支持自定義響應(yīng)處理器,注冊(cè)一個(gè) RateLimitResponseHandler Bean 就行。

三、一些設(shè)計(jì)細(xì)節(jié)

并發(fā)安全

限流對(duì)并發(fā)安全的要求比防重高。你想,10 個(gè)請(qǐng)求同時(shí)進(jìn)來(lái),限流閾值是 5,如果并發(fā)控制沒(méi)做好,可能 10 個(gè)都放過(guò)去了。

Guardian 的處理:

  • Redis:滑動(dòng)窗口和令牌桶都用 Lua 腳本,Redis 單線程執(zhí)行 Lua 是天然原子的
  • 本地緩存:synchronized 鎖到 Key 粒度,不同 Key 之間互不阻塞

防重那邊也是一樣,Redis 用 SET NX EX 原子操作,本地緩存用 ConcurrentHashMap 的原子方法。

本地緩存的內(nèi)存管理

用 ConcurrentHashMap 做本地存儲(chǔ)有個(gè)容易忽略的問(wèn)題:Key 只進(jìn)不出,長(zhǎng)時(shí)間運(yùn)行內(nèi)存會(huì)一直漲。

Guardian 在防重和限流的本地存儲(chǔ)里都加了守護(hù)線程,每 5 分鐘掃一次,清理過(guò)期的 Key。線程是 daemon 的,不會(huì)阻止 JVM 關(guān)閉。源碼可以看 RateLimitLocalStorage。

可插拔架構(gòu)

兩個(gè)模塊的核心組件都是面向接口編程的,框架內(nèi)部用 @ConditionalOnMissingBean 做的,你不注冊(cè)就用默認(rèn)的,注冊(cè)了就用你的:

組件防重復(fù)提交接口限流
Key 生成RepeatSubmitKeyGeneratorRateLimitKeyGenerator
Key 加密AbstractKeyEncryptAbstractKeyEncrypt
存儲(chǔ)RepeatSubmitStorageRateLimitStorage
響應(yīng)處理RepeatSubmitResponseHandlerRateLimitResponseHandler
用戶上下文UserContext(共享)UserContext(共享)

可觀測(cè)性

兩個(gè)模塊都內(nèi)置了監(jiān)控能力:

攔截日志log-enabled: true 開(kāi)啟后,攔截/放行都有日志輸出。

Actuator 端點(diǎn)

GET /actuator/guardianRepeatSubmit    → 防重統(tǒng)計(jì)
GET /actuator/guardianRateLimit       → 限流統(tǒng)計(jì)

限流的統(tǒng)計(jì)數(shù)據(jù)長(zhǎng)這樣:

{
  "totalRequestCount": 5560,
  "totalPassCount": 5432,
  "totalBlockCount": 128,
  "blockRate": "2.30%",
  "topBlockedApis": { "/api/sms/send": 56 },
  "topRequestApis": { "/api/search": 3200 }
}

項(xiàng)目結(jié)構(gòu)

guardian-parent
├── guardian-core                          # 公共基礎(chǔ)(共享類)
├── guardian-repeat-submit/                # 防重復(fù)提交
│   ├── guardian-repeat-submit-core/
│   └── guardian-repeat-submit-spring-boot-starter/
├── guardian-rate-limit/                   # 接口限流
│   ├── guardian-rate-limit-core/
│   └── guardian-rate-limit-spring-boot-starter/
├── guardian-storage-redis/                # Redis 存儲(chǔ)(多模塊共享)
└── guardian-example/                      # 示例工程

模塊拆分是為了靈活組合。比如你只需要防重就引 guardian-repeat-submit-spring-boot-starter,只需要限流就引 guardian-rate-limit-spring-boot-starter,都需要就兩個(gè)都引,互不影響。

guardian-core 放的是兩個(gè)模塊都用到的公共類,比如 UserContext、GuardianResponseHandler。guardian-storage-redis 是 Redis 存儲(chǔ)的共享實(shí)現(xiàn),兩個(gè)模塊的 Redis 存儲(chǔ)都在這里面。

完整的示例代碼在 guardian-example 模塊里,防重 + 限流的各種場(chǎng)景都有,clone 下來(lái)直接跑。

總結(jié)

Guardian 做了兩件事:

  1. 防重復(fù)提交:攔截短時(shí)間內(nèi)的重復(fù)請(qǐng)求,支持注解 / YAML、用戶 / IP / 全局維度、異常自動(dòng)釋放、context-path 兼容
  2. 接口限流:控制接口訪問(wèn)頻率,支持滑動(dòng)窗口 / 令牌桶、突發(fā)流量處理、三種維度

兩個(gè)功能獨(dú)立 Starter,核心組件全部可插拔,注冊(cè) Bean 就能替換默認(rèn)實(shí)現(xiàn)。Redis 和本地緩存一鍵切換。

如果你的 Spring Boot 項(xiàng)目里需要這些能力,但又不想引 Sentinel 那么重的東西,可以試試。

Maven Central 坐標(biāo)(最新 v1.3.0):

<!-- 防重復(fù)提交 -->
<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-repeat-submit-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>
<!-- 接口限流 -->
<dependency>
    <groupId>io.github.biggg-guardian</groupId>
    <artifactId>guardian-rate-limit-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>

項(xiàng)目地址(README 里有完整配置文檔和更新日志):

GitHubhttps://github.com/BigGG-Guardian/guardian/tree/master/guardian-storage-redis

到此這篇關(guān)于SpringBoot 接口防護(hù)(防重提交 + 限流)的文章就介紹到這了,更多相關(guān)SpringBoot 接口防護(hù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?Boot如何處理@Resource示例分析

    Spring?Boot如何處理@Resource示例分析

    這篇文章主要為大家介紹了Spring?Boot如何處理@Resource示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Java中的反射機(jī)制示例詳解

    Java中的反射機(jī)制示例詳解

    反射就是把Java類中的各個(gè)成分映射成一個(gè)個(gè)的Java對(duì)象。本文將通過(guò)示例詳細(xì)講解Java中的反射機(jī)制,感興趣的小伙伴可以跟隨小編學(xué)習(xí)一下
    2022-03-03
  • Spring 自動(dòng)裝配的二義性實(shí)例解析

    Spring 自動(dòng)裝配的二義性實(shí)例解析

    這篇文章主要介紹了Spring 自動(dòng)裝配的二義性實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 使用arthas命令redefine實(shí)現(xiàn)Java熱更新(推薦)

    使用arthas命令redefine實(shí)現(xiàn)Java熱更新(推薦)

    今天分享一個(gè)非常重要的命令 redefine ,主要作用是加載外部的 .class 文件,用來(lái)替換 JVM 已經(jīng)加載的類,總結(jié)起來(lái)就是實(shí)現(xiàn)了 Java 的熱更新,感興趣的朋友跟隨小編一起看看吧
    2020-05-05
  • Spring Boot 簡(jiǎn)介(入門(mén)篇)

    Spring Boot 簡(jiǎn)介(入門(mén)篇)

    Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程。下面通過(guò)本文給大家介紹spring boot相關(guān)知識(shí),需要的的朋友參考下吧
    2017-04-04
  • MyBatis Oracle 自增序列的實(shí)現(xiàn)方法

    MyBatis Oracle 自增序列的實(shí)現(xiàn)方法

    這篇文章給大家分享MyBatis Oracle 自增序列的實(shí)現(xiàn)方法及mybatis配置oracle的主鍵自增長(zhǎng)的方法,非常不錯(cuò)具有一定的參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-11-11
  • 淺析Spring和MyBatis整合及逆向工程

    淺析Spring和MyBatis整合及逆向工程

    這篇文章主要介紹了Spring和MyBatis整合及逆向工程的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • Java代碼審計(jì)的一些基礎(chǔ)知識(shí)你知道嗎

    Java代碼審計(jì)的一些基礎(chǔ)知識(shí)你知道嗎

    這篇文章主要介紹了基于Java的代碼審計(jì)功能的基礎(chǔ)知識(shí),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-09-09
  • java 示例講解循環(huán)語(yǔ)句的使用

    java 示例講解循環(huán)語(yǔ)句的使用

    順序結(jié)構(gòu)的程序語(yǔ)句只能被執(zhí)行一次。如果您想要同樣的操作執(zhí)行多次,就需要使用循環(huán)結(jié)構(gòu),循環(huán)結(jié)構(gòu)就是在循環(huán)條件滿足的情況下,反復(fù)執(zhí)行特定代碼
    2022-04-04
  • idea設(shè)置JVM運(yùn)行參數(shù)的幾種方式

    idea設(shè)置JVM運(yùn)行參數(shù)的幾種方式

    對(duì)JVM運(yùn)行參數(shù)進(jìn)行修改是JVM性能調(diào)優(yōu)的重要手段,本文主要介紹了idea設(shè)置JVM運(yùn)行參數(shù)的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04

最新評(píng)論

顺义区| 临湘市| 柏乡县| 乳源| 巴中市| 德州市| 阜康市| 临泽县| 彝良县| 泸水县| 镇远县| 台东市| 兴山县| 新疆| 阿合奇县| 天峨县| 新化县| 容城县| 广饶县| 云南省| 双牌县| 家居| 墨脱县| 蒲江县| 资兴市| 荥经县| 大化| 乌苏市| 尚志市| 青冈县| 宁陵县| 肇东市| 全州县| 吉安市| 福清市| 东兰县| 育儿| 耒阳市| 芦溪县| 文成县| 湛江市|