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

一文搞懂Java中對象池的實現(xiàn)

 更新時間:2022年07月11日 11:30:12   作者:程序猿阿朗  
池化并不是什么新鮮的技術(shù),它更像一種軟件設(shè)計模式,主要功能是緩存一組已經(jīng)初始化的對象,以供隨時可以使用。本文將為大家詳細(xì)講講Java中對象池的實現(xiàn),需要的可以參考一下

最近在分析一個應(yīng)用中的某個接口的耗時情況時,發(fā)現(xiàn)一個看起來極其普通的對象創(chuàng)建操作,竟然每次需要消耗 8ms 左右時間,分析后發(fā)現(xiàn)這個對象可以通過對象池模式進(jìn)行優(yōu)化,優(yōu)化后此步耗時僅有 0.01ms,這篇文章介紹對象池相關(guān)知識。

1. 什么是對象池

池化并不是什么新鮮的技術(shù),它更像一種軟件設(shè)計模式,主要功能是緩存一組已經(jīng)初始化的對象,以供隨時可以使用。對象池大多數(shù)場景下都是緩存著創(chuàng)建成本過高或者需要重復(fù)創(chuàng)建使用的對象,從池子中取對象的時間是可以預(yù)測的,但是新建一個對象的時間是不確定的。

當(dāng)需要一個新對象時,就向池中借出一個,然后對象池標(biāo)記當(dāng)前對象正在使用,使用完畢后歸還到對象池,以便再次借出。

常見的使用對象池化場景:

  • 1. 對象創(chuàng)建成本過高。
  • 2. 需要頻繁的創(chuàng)建大量重復(fù)對象,會產(chǎn)生很多內(nèi)存碎片。
  • 3. 同時使用的對象不會太多。
  • 4. 常見的具體場景如數(shù)據(jù)庫連接池、線程池等。

2. 為什么需要對象池

如果一個對象的創(chuàng)建成本很高,比如建立數(shù)據(jù)庫的連接時耗時過長,在不使用池化技術(shù)的情況下,我們的查詢過程可能是這樣的。

  • 查詢 1:建立數(shù)據(jù)庫連接 -> 發(fā)起查詢 -> 收到響應(yīng) -> 關(guān)閉連接
  • 查詢 2:建立數(shù)據(jù)庫連接 -> 發(fā)起查詢 -> 收到響應(yīng) -> 關(guān)閉連接
  • 查詢 3:建立數(shù)據(jù)庫連接 -> 發(fā)起查詢 -> 收到響應(yīng) -> 關(guān)閉連接

在這種模式下,每次查詢都要重新建立關(guān)閉連接,因為建立連接是一個耗時的操作,所以這種模式會影響程序的總體性能。

那么使用池化思想是怎么樣的呢?同樣的過程會轉(zhuǎn)變成下面的步驟。

  • 初始化:建立 N 個數(shù)據(jù)庫連接 -> 緩存起來
  • 查詢 1:從緩存借到數(shù)據(jù)庫連接 -> 發(fā)起查詢 -> 收到響應(yīng) -> 歸還數(shù)據(jù)庫連接對象到緩存
  • 查詢 2:從緩存借到數(shù)據(jù)庫連接 -> 發(fā)起查詢 -> 收到響應(yīng) -> 歸還數(shù)據(jù)庫連接對象到緩存
  • 查詢 3:從緩存借到數(shù)據(jù)庫連接 -> 發(fā)起查詢 -> 收到響應(yīng) -> 歸還數(shù)據(jù)庫連接對象到緩存

使用池化思想后,數(shù)據(jù)庫連接并不會頻繁的創(chuàng)建關(guān)閉,而是啟動后就初始化了 N 個連接以供后續(xù)使用,使用完畢后歸還對象,這樣程序的總體性能得到提升。

3. 對象池的實現(xiàn)

通過上面的例子也可以發(fā)現(xiàn)池化思想的幾個關(guān)鍵步驟:初始化、借出、歸還。上面沒有展示銷毀步驟, 某些場景下還需要對象的銷毀這一過程,比如釋放連接。

下面我們手動實現(xiàn)一個簡陋的對象池,加深下對對象池的理解。主要是定一個對象池管理類,然后在里面實現(xiàn)對象的初始化、借出、歸還、銷毀等操作。

package?com.wdbyet.tool.objectpool.mypool;

import?java.io.Closeable;
import?java.io.IOException;
import?java.util.HashSet;
import?java.util.Stack;

/**
?*?@author?https://www.wdbyte.com
?*/
public?class?MyObjectPool<T?extends?Closeable>?{

????//?池子大小
????private?Integer?size?=?5;
????//?對象池棧。后進(jìn)先出
????private?Stack<T>?stackPool?=?new?Stack<>();
????//?借出的對象的?hashCode?集合
????private?HashSet<Integer>?borrowHashCodeSet?=?new?HashSet<>();

????/**
?????*?增加一個對象
?????*
?????*?@param?t
?????*/
????public?synchronized?void?addObj(T?t)?{
????????if?((stackPool.size()?+?borrowHashCodeSet.size())?==?size)?{
????????????throw?new?RuntimeException("池中對象已經(jīng)達(dá)到最大值");
????????}
????????stackPool.add(t);
????????System.out.println("添加了對象:"?+?t.hashCode());
????}

????/**
?????*?借出一個對象
?????*
?????*?@return
?????*/
????public?synchronized?T?borrowObj()?{
????????if?(stackPool.isEmpty())?{
????????????System.out.println("沒有可以被借出的對象");
????????????return?null;
????????}
????????T?pop?=?stackPool.pop();
????????borrowHashCodeSet.add(pop.hashCode());
????????System.out.println("借出了對象:"?+?pop.hashCode());
????????return?pop;
????}

????/**
?????*?歸還一個對象
?????*
?????*?@param?t
?????*/
????public?synchronized?void?returnObj(T?t)?{
????????if?(borrowHashCodeSet.contains(t.hashCode()))?{
????????????stackPool.add(t);
????????????borrowHashCodeSet.remove(t.hashCode());
????????????System.out.println("歸還了對象:"?+?t.hashCode());
????????????return;
????????}
????????throw?new?RuntimeException("只能歸還從池中借出的對象");
????}

????/**
?????*?銷毀池中對象
?????*/
????public?synchronized?void?destory()?{
????????if?(!borrowHashCodeSet.isEmpty())?{
????????????throw?new?RuntimeException("尚有未歸還的對象,不能關(guān)閉所有對象");
????????}
????????while?(!stackPool.isEmpty())?{
????????????T?pop?=?stackPool.pop();
????????????try?{
????????????????pop.close();
????????????}?catch?(IOException?e)?{
????????????????throw?new?RuntimeException(e);
????????????}
????????}
????????System.out.println("已經(jīng)銷毀了所有對象");
????}
}

代碼還是比較簡單的,只是簡單的示例,下面我們通過池化一個 Redis 連接對象 Jedis 來演示如何使用。

其實 Jedis 中已經(jīng)有對應(yīng)的 Jedis 池化管理對象了 JedisPool 了,不過我們這里為了演示對象池的實現(xiàn),就不使用官方提供的 JedisPool 了。

啟動一個 Redis 服務(wù)這里不做介紹,假設(shè)你已經(jīng)有了一個 Redis 服務(wù),下面引入 Java 中連接 Redis 需要用到的 Maven 依賴。

<dependency>
????<groupId>redis.clients</groupId>
????<artifactId>jedis</artifactId>
????<version>4.2.0</version>
</dependency>

正常情況下 Jedis 對象的使用方式:

Jedis?jedis?=?new?Jedis("localhost",?6379);
String?name?=?jedis.get("name");
System.out.println(name);
jedis.close();

如果使用上面的對象池,就可以像下面這樣使用。

package?com.wdbyet.tool.objectpool.mypool;

import?redis.clients.jedis.Jedis;

/**
?*?@author?niulang
?*?@date?2022/07/02
?*/
public?class?MyObjectPoolTest?{

????public?static?void?main(String[]?args)?{
????????MyObjectPool<Jedis>?objectPool?=?new?MyObjectPool<>();
????????//?增加一個?jedis?連接對象
????????objectPool.addObj(new?Jedis("127.0.0.1",?6379));
????????objectPool.addObj(new?Jedis("127.0.0.1",?6379));
????????//?從對象池中借出一個?jedis?對象
????????Jedis?jedis?=?objectPool.borrowObj();
????????//?一次?redis?查詢
????????String?name?=?jedis.get("name");
????????System.out.println(String.format("redis?get:"?+?name));
????????//?歸還?redis?連接對象
????????objectPool.returnObj(jedis);
????????//?銷毀對象池中的所有對象
????????objectPool.destory();
????????//?再次借用對象
????????objectPool.borrowObj();
????}
}

輸出日志:

添加了對象:1556956098
添加了對象:1252585652
借出了對象:1252585652
redis get:www.wdbyte.com
歸還了對象:1252585652
已經(jīng)銷毀了所有對象
沒有可以被借出的對象

如果使用 JMH 對使用對象池化進(jìn)行 Redis 查詢,和正常創(chuàng)建 Redis 連接然后查詢關(guān)閉連接的方式進(jìn)行性能對比,會發(fā)現(xiàn)兩者的性能差異很大。下面是測試結(jié)果,可以發(fā)現(xiàn)使用對象池化后的性能是非池化方式的 5 倍左右。

Benchmark                   Mode  Cnt      Score       Error  Units
MyObjectPoolTest.test      thrpt   15   2612.689 ±   358.767  ops/s
MyObjectPoolTest.testPool  thrpt    9  12414.228 ± 11669.484  ops/s

4. 開源的對象池工具

上面自己實現(xiàn)的對象池總歸有些簡陋了,其實開源工具中已經(jīng)有了非常好用的對象池的實現(xiàn),如 Apache 的 commons-pool2 工具,很多開源工具中的對象池都是基于此工具實現(xiàn),下面介紹這個工具的使用方式。

maven 依賴:

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

在 commons-pool2 對象池工具中有幾個關(guān)鍵的類。

  • • PooledObjectFactory 類是一個工廠接口,用于實現(xiàn)想要池化對象的創(chuàng)建、驗證、銷毀等操作。
  • • GenericObjectPool 類是一個通用的對象池管理類,可以進(jìn)行對象的借出、歸還等操作。
  • • GenericObjectPoolConfig 類是對象池的配置類,可以進(jìn)行對象的最大、最小等容量信息進(jìn)行配置。

下面通過一個具體的示例演示 commons-pool2 工具類的使用,這里依舊選擇 Redis 連接對象 Jedis 作為演示。

實現(xiàn) PooledObjectFactory 工廠類,實現(xiàn)其中的對象創(chuàng)建和銷毀方法。

public?class?MyPooledObjectFactory?implements?PooledObjectFactory<Jedis>?{

????@Override
????public?void?activateObject(PooledObject<Jedis>?pooledObject)?throws?Exception?{

????}

????@Override
????public?void?destroyObject(PooledObject<Jedis>?pooledObject)?throws?Exception?{
????????Jedis?jedis?=?pooledObject.getObject();
????????jedis.close();
??????????System.out.println("釋放連接");
????}

????@Override
????public?PooledObject<Jedis>?makeObject()?throws?Exception?{
????????return?new?DefaultPooledObject(new?Jedis("localhost",?6379));
????}

????@Override
????public?void?passivateObject(PooledObject<Jedis>?pooledObject)?throws?Exception?{
????}

????@Override
????public?boolean?validateObject(PooledObject<Jedis>?pooledObject)?{
????????return?false;
????}
}

繼承 GenericObjectPool 類,實現(xiàn)對對象的借出、歸還等操作。

public?class?MyGenericObjectPool?extends?GenericObjectPool<Jedis>?{

????public?MyGenericObjectPool(PooledObjectFactory?factory)?{
????????super(factory);
????}

????public?MyGenericObjectPool(PooledObjectFactory?factory,?GenericObjectPoolConfig?config)?{
????????super(factory,?config);
????}

????public?MyGenericObjectPool(PooledObjectFactory?factory,?GenericObjectPoolConfig?config,
????????AbandonedConfig?abandonedConfig)?{
????????super(factory,?config,?abandonedConfig);
????}
}

可以看到 MyGenericObjectPool 類的構(gòu)造函數(shù)中的入?yún)⒂?nbsp;GenericObjectPoolConfig 對象,這是個對象池的配置對象,可以配置對象池的容量大小等信息,這里就不配置了,使用默認(rèn)配置。

通過 GenericObjectPoolConfig 的源碼可以看到默認(rèn)配置中,對象池的容量是 8 個

public?class?GenericObjectPoolConfig<T>?extends?BaseObjectPoolConfig<T>?{

????/**
?????*?The?default?value?for?the?{@code?maxTotal}?configuration?attribute.
?????*?@see?GenericObjectPool#getMaxTotal()
?????*/
????public?static?final?int?DEFAULT_MAX_TOTAL?=?8;

????/**
?????*?The?default?value?for?the?{@code?maxIdle}?configuration?attribute.
?????*?@see?GenericObjectPool#getMaxIdle()
?????*/
????public?static?final?int?DEFAULT_MAX_IDLE?=?8;

下面編寫一個對象池使用測試類。

public?class?ApachePool?{

????public?static?void?main(String[]?args)?throws?Exception?{
????????MyGenericObjectPool?objectMyObjectPool?=?new?MyGenericObjectPool(new?MyPooledObjectFactory());
????????Jedis?jedis?=?objectMyObjectPool.borrowObject();
????????String?name?=?jedis.get("name");
????????System.out.println(name);
????????objectMyObjectPool.returnObject(jedis);
????????objectMyObjectPool.close();
????}

}

輸出日志:

redis get:www.wdbyte.com
釋放連接

上面已經(jīng)演示了 commons-pool2 工具中的對象池的使用方式,從上面的例子中可以發(fā)現(xiàn)這種對象池中只能存放同一種初始化條件的對象,如果這里的 Redis 我們需要存儲一個本地連接和一個遠(yuǎn)程連接的兩種 Jedis 對象,就不能滿足了。那么怎么辦呢?

其實 commons-pool2 工具已經(jīng)考慮到了這種情況,通過增加一個 key 值可以在同一個對象池管理中進(jìn)行區(qū)分,代碼和上面類似,直接貼出完整的代碼實現(xiàn)。

package?com.wdbyet.tool.objectpool.apachekeyedpool;

import?org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
import?org.apache.commons.pool2.KeyedPooledObjectFactory;
import?org.apache.commons.pool2.PooledObject;
import?org.apache.commons.pool2.impl.AbandonedConfig;
import?org.apache.commons.pool2.impl.DefaultPooledObject;
import?org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import?org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import?redis.clients.jedis.Jedis;

/**
?*?@author?https://www.wdbyte.com
?*?@date?2022/07/07
?*/
public?class?ApacheKeyedPool?{

????public?static?void?main(String[]?args)?throws?Exception?{
????????String?key?=?"local";
????????MyGenericKeyedObjectPool?objectMyObjectPool?=?new?MyGenericKeyedObjectPool(new?MyKeyedPooledObjectFactory());
????????Jedis?jedis?=?objectMyObjectPool.borrowObject(key);
????????String?name?=?jedis.get("name");
????????System.out.println("redis?get?:"?+?name);
????????objectMyObjectPool.returnObject(key,?jedis);
????}
}

class?MyKeyedPooledObjectFactory?extends?BaseKeyedPooledObjectFactory<String,?Jedis>?{

????@Override
????public?Jedis?create(String?key)?throws?Exception?{
????????if?("local".equals(key))?{
????????????return?new?Jedis("localhost",?6379);
????????}
????????if?("remote".equals(key))?{
????????????return?new?Jedis("192.168.0.105",?6379);
????????}
????????return?null;
????}

????@Override
????public?PooledObject<Jedis>?wrap(Jedis?value)?{
????????return?new?DefaultPooledObject<>(value);
????}
}

class?MyGenericKeyedObjectPool?extends?GenericKeyedObjectPool<String,?Jedis>?{

????public?MyGenericKeyedObjectPool(KeyedPooledObjectFactory<String,?Jedis>?factory)?{
????????super(factory);
????}

????public?MyGenericKeyedObjectPool(KeyedPooledObjectFactory<String,?Jedis>?factory,
????????GenericKeyedObjectPoolConfig<Jedis>?config)?{
????????super(factory,?config);
????}

????public?MyGenericKeyedObjectPool(KeyedPooledObjectFactory<String,?Jedis>?factory,
????????GenericKeyedObjectPoolConfig<Jedis>?config,?AbandonedConfig?abandonedConfig)?{
????????super(factory,?config,?abandonedConfig);
????}
}

輸出日志:

redis get :www.wdbyte.com

5. JedisPool 對象池實現(xiàn)分析

這篇文章中的演示都使用了 Jedis 連接對象,其實在 Jedis SDK 中已經(jīng)實現(xiàn)了相應(yīng)的對象池,也就是我們常用的 JedisPool 類。那么這里的 JedisPool 是怎么實現(xiàn)的呢?我們先看一下 JedisPool 的使用方式。

package?com.wdbyet.tool.objectpool;

import?redis.clients.jedis.Jedis;
import?redis.clients.jedis.JedisPool;

/**
?*?@author?https://www.wdbyte.com
?*/
public?class?JedisPoolTest?{

????public?static?void?main(String[]?args)?{
????????JedisPool?jedisPool?=?new?JedisPool("localhost",?6379);
????????//?從對象池中借一個對象
????????Jedis?jedis?=?jedisPool.getResource();
????????String?name?=?jedis.get("name");
????????System.out.println("redis?get?:"?+?name);
????????jedis.close();
????????//?徹底退出前,關(guān)閉?Redis?連接池
????????jedisPool.close();
????}
}

代碼中添加了注釋,可以看到通過 jedisPool.getResource() 拿到了一個對象,這里和上面 commons-pool2 工具中的 borrowObject 十分相似,繼續(xù)追蹤它的代碼實現(xiàn)可以看到下面的代碼。

//?redis.clients.jedis.JedisPool
//?public?class?JedisPool?extends?Pool<Jedis>?{
public?Jedis?getResource()?{
????Jedis?jedis?=?(Jedis)super.getResource();
????jedis.setDataSource(this);
????return?jedis;
}
//?繼續(xù)追蹤?super.getResource()
//?redis.clients.jedis.util.Pool
public?T?getResource()?{
????try?{
????????return?super.borrowObject();
????}?catch?(JedisException?var2)?{
????????throw?var2;
????}?catch?(Exception?var3)?{
????????throw?new?JedisException("Could?not?get?a?resource?from?the?pool",?var3);
????}
}

竟然看到了 super.borrowObject() ,多么熟悉的方法,繼續(xù)分析代碼可以發(fā)現(xiàn) Jedis 對象池也是使用了 commons-pool2 工具作為實現(xiàn)。既然如此,那么 jedis.close() 方法的邏輯我們應(yīng)該也可以猜到了,應(yīng)該有一個歸還的操作,查看代碼發(fā)現(xiàn)果然如此。

//?redis.clients.jedis.JedisPool
//?public?class?JedisPool?extends?Pool<Jedis>?{
public?void?close()?{
????if?(this.dataSource?!=?null)?{
????????Pool<Jedis>?pool?=?this.dataSource;
????????this.dataSource?=?null;
????????if?(this.isBroken())?{
????????????pool.returnBrokenResource(this);
????????}?else?{
????????????pool.returnResource(this);
????????}
????}?else?{
????????this.connection.close();
????}
}
//?繼續(xù)追蹤?super.getResource()
//?redis.clients.jedis.util.Pool
public?void?returnResource(T?resource)?{
????if?(resource?!=?null)?{
????????try?{
????????????super.returnObject(resource);
????????}?catch?(RuntimeException?var3)?{
????????????throw?new?JedisException("Could?not?return?the?resource?to?the?pool",?var3);
????????}
????}
}

通過上面的分析,可見 Jedis 確實使用了 commons-pool2 工具進(jìn)行對象池的管理,通過分析 JedisPool 類的繼承關(guān)系圖也可以發(fā)現(xiàn)。

JedisPool 繼承關(guān)系

6. 對象池總結(jié)

通過這篇文章的介紹,可以發(fā)現(xiàn)池化思想有幾個明顯的優(yōu)勢。

  • 1. 可以顯著的提高應(yīng)用程序的性能。
  • 2. 如果一個對象創(chuàng)建成本過高,那么使用池化非常有效。
  • 3. 池化提供了一種對象的管理以及重復(fù)使用的方式,減少內(nèi)存碎片。
  • 4. 可以為對象的創(chuàng)建數(shù)量提供限制,對某些對象不能創(chuàng)建過多的場景提供保護(hù)。

但是使用對象池化也有一些需要注意的地方,比如歸還對象時應(yīng)確保對象已經(jīng)被重置為可以重復(fù)使用的狀態(tài)。同時也要注意,使用池化時要根據(jù)具體的場景合理的設(shè)置池子的大小,過小達(dá)不到想要的效果,過大會造成內(nèi)存浪費(fèi)。

以上就是一文搞懂Java中對象池的實現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Java對象池的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中的異步回調(diào)問題

    Java中的異步回調(diào)問題

    這篇文章主要介紹了Java中的異步回調(diào)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • JAVA動態(tài)維度笛卡爾積輸出的實現(xiàn)

    JAVA動態(tài)維度笛卡爾積輸出的實現(xiàn)

    本文主要介紹了JAVA動態(tài)維度笛卡爾積輸出的實現(xiàn),通過動態(tài)生成笛卡爾積,可以方便地處理多維數(shù)據(jù)集,提高數(shù)據(jù)處理效率,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • java可以作為第一門編程語言學(xué)習(xí)嗎

    java可以作為第一門編程語言學(xué)習(xí)嗎

    在本篇內(nèi)容里小編給JAVA零基礎(chǔ)的網(wǎng)友分享一篇關(guān)于java可以作為第一門編程語言學(xué)習(xí)嗎的文章,有興趣的朋友們可以參考下。
    2020-11-11
  • 五個很實用的IDEA使用技巧分享

    五個很實用的IDEA使用技巧分享

    IntelliJ IDEA 是一款優(yōu)秀的 Java 集成開發(fā)環(huán)境,它提供了許多強(qiáng)大的功能和快捷鍵,可以幫助開發(fā)者提高編碼效率和質(zhì)量,本文就在為你介紹博主常用的五個IntelliJ IDEA使用技巧,希望能夠給你帶來一些工作效率上的提升
    2023-10-10
  • Java內(nèi)部類詳解

    Java內(nèi)部類詳解

    內(nèi)部類在 Java 里面算是非常常見的一個功能了,在日常開發(fā)中我們肯定多多少少都用過,這里總結(jié)一下關(guān)于 Java 中內(nèi)部類的相關(guān)知識點和一些使用內(nèi)部類時需要注意的點。
    2020-02-02
  • java頁面中文亂碼的解決辦法

    java頁面中文亂碼的解決辦法

    做java開發(fā)的朋友碰到最多的就是中文亂碼這個問題了,下面介紹頁面提交時與url中文亂碼的一些解決辦法
    2013-11-11
  • Eclipse添加servlet模板過程代碼詳解

    Eclipse添加servlet模板過程代碼詳解

    這篇文章主要介紹了Eclipse添加servlet模板過程代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • 淺談web項目讀取classpath路徑下面的文件

    淺談web項目讀取classpath路徑下面的文件

    這篇文章主要介紹了淺談web項目讀取classpath路徑下面的文件,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • 詳解Java的Spring框架中的事務(wù)管理方式

    詳解Java的Spring框架中的事務(wù)管理方式

    這篇文章主要介紹了Java的Spring框架中的事務(wù)管理方式,Spring框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下
    2015-12-12
  • SpringBoot里使用Servlet進(jìn)行請求的實現(xiàn)示例

    SpringBoot里使用Servlet進(jìn)行請求的實現(xiàn)示例

    這篇文章主要介紹了SpringBoot里使用Servlet進(jìn)行請求的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論