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

SpringBoot?HikariCP連接池詳解

 更新時(shí)間:2022年08月16日 08:37:36   作者:Java海  
這篇文章主要介紹了SpringBoot2.0?中?HikariCP?數(shù)據(jù)庫(kù)連接池原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

背景

在我們平常的編碼中,通常會(huì)將一些對(duì)象保存起來(lái),這主要考慮的是對(duì)象的創(chuàng)建成本。

比如像線程資源、數(shù)據(jù)庫(kù)連接資源或者 TCP 連接等,這類對(duì)象的初始化通常要花費(fèi)比較長(zhǎng)的時(shí)間,如果頻繁地申請(qǐng)和銷毀,就會(huì)耗費(fèi)大量的系統(tǒng)資源,造成不必要的性能損失。

并且這些對(duì)象都有一個(gè)顯著的特征,就是通過(guò)輕量級(jí)的重置工作,可以循環(huán)、重復(fù)地使用。

這個(gè)時(shí)候,我們就可以使用一個(gè)虛擬的池子,將這些資源保存起來(lái),當(dāng)使用的時(shí)候,我們就從池子里快速獲取一個(gè)即可。

在 Java 中,池化技術(shù)應(yīng)用非常廣泛,常見的就有數(shù)據(jù)庫(kù)連接池、線程池等,本文主講連接池,線程池我們將在后續(xù)的博客中進(jìn)行介紹。

公用池化包 Commons Pool 2

我們首先來(lái)看一下 Java 中公用的池化包 Commons Pool 2,來(lái)了解一下對(duì)象池的一般結(jié)構(gòu)。

根據(jù)我們的業(yè)務(wù)需求,使用這套 API 能夠很容易實(shí)現(xiàn)對(duì)象的池化管理。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.11.1</version>
</dependency>

GenericObjectPool 是對(duì)象池的核心類,通過(guò)傳入一個(gè)對(duì)象池的配置和一個(gè)對(duì)象的工廠,即可快速創(chuàng)建對(duì)象池。

public GenericObjectPool( 
            final PooledObjectFactory<T> factory, 
            final GenericObjectPoolConfig<T> config)

案例

Redis 的常用客戶端 Jedis,就是使用 Commons Pool 管理連接池的,可以說(shuō)是一個(gè)最佳實(shí)踐。下圖是 Jedis 使用工廠創(chuàng)建對(duì)象的主要代碼塊。

對(duì)象工廠類最主要的方法就是makeObject,它的返回值是 PooledObject 類型,可以將對(duì)象使用 new DefaultPooledObject<>(obj) 進(jìn)行簡(jiǎn)單包裝返回。

redis.clients.jedis.JedisFactory,使用工廠創(chuàng)建對(duì)象。

@Override
public PooledObject<Jedis> makeObject() throws Exception {
  Jedis jedis = null;
  try {
    jedis = new Jedis(jedisSocketFactory, clientConfig);
    //主要的耗時(shí)操作
    jedis.connect();
    //返回包裝對(duì)象
    return new DefaultPooledObject<>(jedis);
  } catch (JedisException je) {
    if (jedis != null) {
      try {
        jedis.quit();
      } catch (RuntimeException e) {
        logger.warn("Error while QUIT", e);
      }
      try {
        jedis.close();
      } catch (RuntimeException e) {
        logger.warn("Error while close", e);
      }
    }
    throw je;
  }
}

我們?cè)賮?lái)介紹一下對(duì)象的生成過(guò)程,如下圖,對(duì)象在進(jìn)行獲取時(shí),將首先嘗試從對(duì)象池里拿出一個(gè),如果對(duì)象池中沒(méi)有空閑的對(duì)象,就使用工廠類提供的方法,生成一個(gè)新的。

public T borrowObject(final Duration borrowMaxWaitDuration) throws Exception {
    //此處省略若干行
    while (p == null) {
        create = false;
        //首先嘗試從池子中獲取。
        p = idleObjects.pollFirst();
        // 池子里獲取不到,才調(diào)用工廠內(nèi)生成新實(shí)例
        if (p == null) {
            p = create();
            if (p != null) {
                create = true;
            }
        }
        //此處省略若干行
    }
    //此處省略若干行
}

那對(duì)象是存在什么地方的呢?這個(gè)存儲(chǔ)的職責(zé),就是由一個(gè)叫作LinkedBlockingDeque 的結(jié)構(gòu)來(lái)承擔(dān)的,它是一個(gè)雙向的隊(duì)列。

接下來(lái)看一下 GenericObjectPoolConfig 的主要屬性:

// GenericObjectPoolConfig本身的屬性
private int maxTotal = DEFAULT_MAX_TOTAL;
private int maxIdle = DEFAULT_MAX_IDLE;
private int minIdle = DEFAULT_MIN_IDLE;
// 其父類BaseObjectPoolConfig的屬性
private boolean lifo = DEFAULT_LIFO;
private boolean fairness = DEFAULT_FAIRNESS;
private long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS;
private long minEvictableIdleTimeMillis = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private long evictorShutdownTimeoutMillis = DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS;
private long softMinEvictableIdleTimeMillis = DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
private int numTestsPerEvictionRun = DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
private EvictionPolicy<T> evictionPolicy = null; 
// Only 2.6.0 applications set this 
private String evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME;
private boolean testOnCreate = DEFAULT_TEST_ON_CREATE;
private boolean testOnBorrow = DEFAULT_TEST_ON_BORROW;
private boolean testOnReturn = DEFAULT_TEST_ON_RETURN;
private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE;
private long timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED;

參數(shù)很多,要想了解參數(shù)的意義,我們首先來(lái)看一下一個(gè)池化對(duì)象在整個(gè)池子中的生命周期。

如下圖所示,池子的操作主要有兩個(gè):一個(gè)是業(yè)務(wù)線程,一個(gè)是檢測(cè)線程。

對(duì)象池在進(jìn)行初始化時(shí),要指定三個(gè)主要的參數(shù):

  • maxTotal 對(duì)象池中管理的對(duì)象上限
  • maxIdle 最大空閑數(shù)
  • minIdle 最小空閑數(shù)

其中 maxTotal 和業(yè)務(wù)線程有關(guān),當(dāng)業(yè)務(wù)線程想要獲取對(duì)象時(shí),會(huì)首先檢測(cè)是否有空閑的對(duì)象。

如果有,則返回一個(gè);否則進(jìn)入創(chuàng)建邏輯。此時(shí),如果池中個(gè)數(shù)已經(jīng)達(dá)到了最大值,就會(huì)創(chuàng)建失敗,返回空對(duì)象。

對(duì)象在獲取的時(shí)候,有一個(gè)非常重要的參數(shù),那就是最大等待時(shí)間(maxWaitMillis),這個(gè)參數(shù)對(duì)應(yīng)用方的性能影響是比較大的。該參數(shù)默認(rèn)為 -1,表示永不超時(shí),直到有對(duì)象空閑。

如下圖,如果對(duì)象創(chuàng)建非常緩慢或者使用非常繁忙,業(yè)務(wù)線程會(huì)持續(xù)阻塞 (blockWhenExhausted 默認(rèn)為 true),進(jìn)而導(dǎo)致正常服務(wù)也不能運(yùn)行。

面試題

一般面試官會(huì)問(wèn):你會(huì)把超時(shí)參數(shù)設(shè)置成多大呢?我一般都會(huì)把最大等待時(shí)間,設(shè)置成接口可以忍受的最大延遲。

比如,一個(gè)正常服務(wù)響應(yīng)時(shí)間 10ms 左右,達(dá)到 1 秒鐘就會(huì)感覺(jué)到卡頓,那么這個(gè)參數(shù)設(shè)置成 500~1000ms 都是可以的。

超時(shí)之后,會(huì)拋出 NoSuchElementException 異常,請(qǐng)求會(huì)快速失敗,不會(huì)影響其他業(yè)務(wù)線程,這種 Fail Fast 的思想,在互聯(lián)網(wǎng)應(yīng)用非常廣泛。

帶有 evcit 字樣的參數(shù),主要是處理對(duì)象逐出的。池化對(duì)象除了初始化和銷毀的時(shí)候比較昂貴,在運(yùn)行時(shí)也會(huì)占用系統(tǒng)資源。

比如,連接池會(huì)占用多條連接,線程池會(huì)增加調(diào)度開銷等。業(yè)務(wù)在突發(fā)流量下,會(huì)申請(qǐng)到超出正常情況的對(duì)象資源,放在池子中。等這些對(duì)象不再被使用,我們就需要把它清理掉。

超出 minEvictableIdleTimeMillis 參數(shù)指定值的對(duì)象,就會(huì)被強(qiáng)制回收掉,這個(gè)值默認(rèn)是 30 分鐘;softMinEvictableIdleTimeMillis 參數(shù)類似,但它只有在當(dāng)前對(duì)象數(shù)量大于 minIdle 的時(shí)候才會(huì)執(zhí)行移除,所以前者的動(dòng)作要更暴力一些。

還有 4 個(gè) test 參數(shù):testOnCreate、testOnBorrow、testOnReturn、testWhileIdle,分別指定了在創(chuàng)建、獲取、歸還、空閑檢測(cè)的時(shí)候,是否對(duì)池化對(duì)象進(jìn)行有效性檢測(cè)。

開啟這些檢測(cè),能保證資源的有效性,但它會(huì)耗費(fèi)性能,所以默認(rèn)為 false。

生產(chǎn)環(huán)境上,建議只將 testWhileIdle 設(shè)置為 true,并通過(guò)調(diào)整空閑檢測(cè)時(shí)間間隔(timeBetweenEvictionRunsMillis),比如 1 分鐘,來(lái)保證資源的可用性,同時(shí)也保證效率。

JMH 測(cè)試

使用連接池和不使用連接池,它們之間的性能差距到底有多大呢?

下面是一個(gè)簡(jiǎn)單的 JMH 測(cè)試?yán)樱ㄒ妭}(cāng)庫(kù)),進(jìn)行一個(gè)簡(jiǎn)單的 set 操作,為 redis 的 key 設(shè)置一個(gè)隨機(jī)值。

@Fork(2)
@State(Scope.Benchmark)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@BenchmarkMode(Mode.Throughput)
public class JedisPoolVSJedisBenchmark { 
   JedisPool pool = new JedisPool("localhost", 6379); 
@Benchmarkpublicvoid testPool() { 
    Jedis jedis = pool.getResource(); jedis.set("a", UUID.randomUUID().toString()); 
    jedis.close();
}
@Benchmarkpublicvoid testJedis() { 
    Jedis jedis = new Jedis("localhost",6379); 
    jedis.set("a", UUID.randomUUID().toString()); 
    jedis.close(); 
}//此處省略若干行}

將測(cè)試結(jié)果使用 meta-chart 作圖,展示結(jié)果如下圖所示,可以看到使用了連接池的方式,它的吞吐量是未使用連接池方式的 5 倍!

數(shù)據(jù)庫(kù)連接池 HikariCP

HikariCP 源于日語(yǔ)“光る”,光的意思,寓意軟件工作速度和光速一樣快,它是 SpringBoot 中默認(rèn)的數(shù)據(jù)庫(kù)連接池。

數(shù)據(jù)庫(kù)是我們工作中經(jīng)常使用到的組件,針對(duì)數(shù)據(jù)庫(kù)設(shè)計(jì)的客戶端連接池是非常多的,它的設(shè)計(jì)原理與我們?cè)诒疚拈_頭提到的基本一致,可以有效地減少數(shù)據(jù)庫(kù)連接創(chuàng)建、銷毀的資源消耗。

同是連接池,它們的性能也是有差別的,下圖是 HikariCP 官方的一張測(cè)試圖,可以看到它優(yōu)異的性能,官方的 JMH 測(cè)試代碼見 Github。

一般面試題是這么問(wèn)的:HikariCP 為什么快呢?

主要有三個(gè)方面:

  • 它使用 FastList 替代 ArrayList,通過(guò)初始化的默認(rèn)值,減少了越界檢查的操作
  • 優(yōu)化并精簡(jiǎn)了字節(jié)碼,通過(guò)使用 Javassist,減少了動(dòng)態(tài)代理的性能損耗,比如使用 invokestatic 指令代替 invokevirtual 指令
  • 實(shí)現(xiàn)了無(wú)鎖的 ConcurrentBag,減少了并發(fā)場(chǎng)景下的鎖競(jìng)爭(zhēng)

HikariCP 對(duì)性能的一些優(yōu)化操作,是非常值得我們借鑒的,在之后的博客中,我們將詳細(xì)分析幾個(gè)優(yōu)化場(chǎng)景。

數(shù)據(jù)庫(kù)連接池同樣面臨一個(gè)最大值(maximumPoolSize)和最小值(minimumIdle)的問(wèn)題。這里同樣有一個(gè)非常高頻的面試題:你平常會(huì)把連接池設(shè)置成多大呢?

很多同學(xué)認(rèn)為,連接池的大小設(shè)置得越大越好,有的同學(xué)甚至把這個(gè)值設(shè)置成 1000 以上,這是一種誤解。

根據(jù)經(jīng)驗(yàn),數(shù)據(jù)庫(kù)連接,只需要 20~50 個(gè)就夠用了。具體的大小,要根據(jù)業(yè)務(wù)屬性進(jìn)行調(diào)整,但大得離譜肯定是不合適的。

HikariCP 官方是不推薦設(shè)置 minimumIdle 這個(gè)值的,它將被默認(rèn)設(shè)置成和 maximumPoolSize 一樣的大小。如果你的數(shù)據(jù)庫(kù)Server端連接資源空閑較大,不妨也可以去掉連接池的動(dòng)態(tài)調(diào)整功能。

另外,根據(jù)數(shù)據(jù)庫(kù)查詢和事務(wù)類型,一個(gè)應(yīng)用中是可以配置多個(gè)數(shù)據(jù)庫(kù)連接池的,這個(gè)優(yōu)化技巧很少有人知道,在此簡(jiǎn)要描述一下。

業(yè)務(wù)類型通常有兩種:一種需要快速的響應(yīng)時(shí)間,把數(shù)據(jù)盡快返回給用戶;另外一種是可以在后臺(tái)慢慢執(zhí)行,耗時(shí)比較長(zhǎng),對(duì)時(shí)效性要求不高。

如果這兩種業(yè)務(wù)類型,共用一個(gè)數(shù)據(jù)庫(kù)連接池,就容易發(fā)生資源爭(zhēng)搶,進(jìn)而影響接口響應(yīng)速度。

雖然微服務(wù)能夠解決這種情況,但大多數(shù)服務(wù)是沒(méi)有這種條件的,這時(shí)就可以對(duì)連接池進(jìn)行拆分。

如圖,在同一個(gè)業(yè)務(wù)中,根據(jù)業(yè)務(wù)的屬性,我們分了兩個(gè)連接池,就是來(lái)處理這種情況的。

HikariCP 還提到了另外一個(gè)知識(shí)點(diǎn),在 JDBC4 的協(xié)議中,通過(guò) Connection.isValid() 就可以檢測(cè)連接的有效性。

這樣,我們就不用設(shè)置一大堆的 test 參數(shù)了,HikariCP 也沒(méi)有提供這樣的參數(shù)。

結(jié)果緩存池

到了這里你可能會(huì)發(fā)現(xiàn)池(Pool)與緩存(Cache)有許多相似之處。

它們之間的一個(gè)共同點(diǎn),就是將對(duì)象加工后,存儲(chǔ)在相對(duì)高速的區(qū)域。我習(xí)慣性將緩存看作是數(shù)據(jù)對(duì)象,而把池中的對(duì)象看作是執(zhí)行對(duì)象。緩存中的數(shù)據(jù)有一個(gè)命中率問(wèn)題,而池中的對(duì)象一般都是對(duì)等的。

考慮下面一個(gè)場(chǎng)景,jsp 提供了網(wǎng)頁(yè)的動(dòng)態(tài)功能,它可以在執(zhí)行后,編譯成 class 文件,加快執(zhí)行速度;再或者,一些媒體平臺(tái),會(huì)將熱門文章,定時(shí)轉(zhuǎn)化成靜態(tài)的 html 頁(yè)面,僅靠 nginx 的負(fù)載均衡即可應(yīng)對(duì)高并發(fā)請(qǐng)求(動(dòng)靜分離)。

這些時(shí)候,你很難說(shuō)清楚,這是針對(duì)緩存的優(yōu)化,還是針對(duì)對(duì)象進(jìn)行了池化,它們?cè)诒举|(zhì)上只是保存了某個(gè)執(zhí)行步驟的結(jié)果,使得下次訪問(wèn)時(shí)不需要從頭再來(lái)。

我通常把這種技術(shù)叫作結(jié)果緩存池(Result Cache Pool),屬于多種優(yōu)化手段的綜合。

小結(jié)

下面我來(lái)簡(jiǎn)單總結(jié)一下本文的內(nèi)容重點(diǎn):我們從 Java 中最通用的公用池化包 Commons Pool 2 說(shuō)起,介紹了它的一些實(shí)現(xiàn)細(xì)節(jié),并對(duì)一些重要參數(shù)的應(yīng)用做了講解。

Jedis 就是在 Commons Pool 2 的基礎(chǔ)上封裝的,通過(guò) JMH 測(cè)試,我們發(fā)現(xiàn)對(duì)象池化之后,有了接近 5 倍的性能提升。

接下來(lái)介紹了數(shù)據(jù)庫(kù)連接池中速度很快的 HikariCP ,它在池化技術(shù)之上,又通過(guò)編碼技巧進(jìn)行了進(jìn)一步的性能提升,HikariCP 是我重點(diǎn)研究的類庫(kù)之一,我也建議你加入自己的任務(wù)清單中。

總體來(lái)說(shuō),當(dāng)你遇到下面的場(chǎng)景,就可以考慮使用池化來(lái)增加系統(tǒng)性能:

  • 對(duì)象的創(chuàng)建或者銷毀,需要耗費(fèi)較多的系統(tǒng)資源
  • 對(duì)象的創(chuàng)建或者銷毀,耗時(shí)長(zhǎng),需要繁雜的操作和較長(zhǎng)時(shí)間的等待
  • 對(duì)象創(chuàng)建后,通過(guò)一些狀態(tài)重置,可被反復(fù)使用

將對(duì)象池化之后,只是開啟了第一步優(yōu)化。要想達(dá)到最優(yōu)性能,就不得不調(diào)整池的一些關(guān)鍵參數(shù),合理的池大小加上合理的超時(shí)時(shí)間,就可以讓池發(fā)揮更大的價(jià)值。和緩存的命中率類似,對(duì)池的監(jiān)控也是非常重要的。

如下圖,可以看到數(shù)據(jù)庫(kù)連接池連接數(shù)長(zhǎng)時(shí)間保持在高位不釋放,同時(shí)等待的線程數(shù)急劇增加,這就能幫我們快速定位到數(shù)據(jù)庫(kù)的事務(wù)問(wèn)題。

平常的編碼中,有很多類似的場(chǎng)景。比如 Http 連接池,Okhttp 和 Httpclient 就都提供了連接池的概念,你可以類比著去分析一下,關(guān)注點(diǎn)也是在連接大小和超時(shí)時(shí)間上。

在底層的中間件,比如 RPC,也通常使用連接池技術(shù)加速資源獲取,比如 Dubbo 連接池、 Feign 切換成 httppclient 的實(shí)現(xiàn)等技術(shù)。

你會(huì)發(fā)現(xiàn),在不同資源層面的池化設(shè)計(jì)也是類似的。比如線程池,通過(guò)隊(duì)列對(duì)任務(wù)進(jìn)行了二層緩沖,提供了多樣的拒絕策略等,線程池我們將在后續(xù)的文章中進(jìn)行介紹。

線程池的這些特性,你同樣可以借鑒到連接池技術(shù)中,用來(lái)緩解請(qǐng)求溢出,創(chuàng)建一些溢出策略。

現(xiàn)實(shí)情況中,我們也會(huì)這么做。那么具體怎么做?有哪些做法?這部分內(nèi)容就留給大家思考了。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ykq</groupId>
    <artifactId>qy151-springboot-vue</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>qy151-springboot-vue</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.9.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

到此這篇關(guān)于SpringBoot HikariCP連接池詳解的文章就介紹到這了,更多相關(guān)SpringBoot HikariCP內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在Spring中配置Quartz的三種方式

    在Spring中配置Quartz的三種方式

    Spring Quartz 是一個(gè)任務(wù)調(diào)度框架,它允許我們定期執(zhí)行特定的任務(wù),在 Spring 中,我們可以通過(guò)多種方式來(lái)配置 Quartz,包括使用 ??@Scheduled?? 注解、XML 配置和 Java 配置,本文將介紹如何在 Spring 中使用這三種方式來(lái)配置 Quartz,需要的朋友可以參考下
    2025-01-01
  • SpringMVC使用ResponseEntity實(shí)現(xiàn)文件上傳下載

    SpringMVC使用ResponseEntity實(shí)現(xiàn)文件上傳下載

    這篇文章主要為大家介紹了SpringMVC使用ResponseEntity實(shí)現(xiàn)文件上傳下載,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • java鏈?zhǔn)絼?chuàng)建json對(duì)象的實(shí)現(xiàn)

    java鏈?zhǔn)絼?chuàng)建json對(duì)象的實(shí)現(xiàn)

    本文主要介紹了java中如何通過(guò)最簡(jiǎn)單的方式實(shí)現(xiàn)鏈?zhǔn)絼?chuàng)建json對(duì)象,解決創(chuàng)建json代碼臃腫的問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java實(shí)現(xiàn)的RSA加密解密算法示例

    Java實(shí)現(xiàn)的RSA加密解密算法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的RSA加密解密算法,結(jié)合實(shí)例形式分析了java RAS加密解密算法的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2018-01-01
  • Spring?Security內(nèi)置過(guò)濾器的維護(hù)方法

    Spring?Security內(nèi)置過(guò)濾器的維護(hù)方法

    這篇文章主要介紹了Spring?Security的內(nèi)置過(guò)濾器是如何維護(hù)的,本文給我們分析一下HttpSecurity維護(hù)過(guò)濾器的幾個(gè)方法,需要的朋友可以參考下
    2022-02-02
  • 基于Java語(yǔ)言實(shí)現(xiàn)Socket通信的實(shí)例

    基于Java語(yǔ)言實(shí)現(xiàn)Socket通信的實(shí)例

    今天小編就為大家分享一篇關(guān)于基于Java語(yǔ)言實(shí)現(xiàn)Socket通信的實(shí)例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • JAVA實(shí)現(xiàn)深拷貝的幾種方式代碼

    JAVA實(shí)現(xiàn)深拷貝的幾種方式代碼

    這篇文章主要給大家介紹了關(guān)于JAVA實(shí)現(xiàn)深拷貝的幾種方式,在Java中深拷貝和淺拷貝是用來(lái)復(fù)制對(duì)象的兩種不同方式,深拷貝會(huì)對(duì)所有數(shù)據(jù)類型進(jìn)行拷貝,包括對(duì)象所包含的內(nèi)部對(duì)象,需要的朋友可以參考下
    2023-09-09
  • 深入理解Spring Boot屬性配置文件

    深入理解Spring Boot屬性配置文件

    這篇文章主要給大家深入的介紹了關(guān)于Spring Boot屬性配置文件的相關(guān)資料,文中介紹的很詳細(xì),相信對(duì)大家具有一定的參考借鑒價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-02-02
  • java  自定義注解的實(shí)例詳解

    java 自定義注解的實(shí)例詳解

    這篇文章主要介紹了java 自定義注解的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-09-09
  • Java實(shí)現(xiàn)布隆過(guò)濾器的方法步驟

    Java實(shí)現(xiàn)布隆過(guò)濾器的方法步驟

    布隆過(guò)濾器是可以用于判斷一個(gè)元素是不是在一個(gè)集合里,并且相比于其它的數(shù)據(jù)結(jié)構(gòu),布隆過(guò)濾器在空間和時(shí)間方面都有巨大的優(yōu)勢(shì)。下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)布隆過(guò)濾器的相關(guān)資料,需要的朋友可以參考下
    2018-11-11

最新評(píng)論