解讀Druid參數(shù)配置全過程
簡(jiǎn)介
Java 程序很大一部分要操作數(shù)據(jù)庫(kù),為了提高性能操作數(shù)據(jù)庫(kù)的時(shí)候,又不得不使用數(shù)據(jù)庫(kù)連接池。
- Druid 是阿里巴巴開源平臺(tái)上一個(gè)數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn),結(jié)合了 C3P0、DBCP 等 DB 池的優(yōu)點(diǎn),同時(shí)加入了日志監(jiān)控。
- Druid 可以很好的監(jiān)控 DB 池連接和 SQL 的執(zhí)行情況,天生就是針對(duì)監(jiān)控而生的 DB 連接池。
- Druid 已經(jīng)在阿里巴巴部署了超過600個(gè)應(yīng)用,經(jīng)過一年多生產(chǎn)環(huán)境大規(guī)模部署的嚴(yán)苛考驗(yàn)。
- Spring Boot 2.0 以上默認(rèn)使用 Hikari 數(shù)據(jù)源,Hikari 與 Driud 都是當(dāng)前 Java Web 上最優(yōu)秀的數(shù)據(jù)源。
連接
當(dāng)我們程序需要訪問數(shù)據(jù)庫(kù)時(shí),需要?jiǎng)?chuàng)建一個(gè)本地到數(shù)據(jù)庫(kù)服務(wù)的網(wǎng)絡(luò)連接,此時(shí)本地代碼就相當(dāng)于一個(gè)數(shù)據(jù)庫(kù)的客戶端,可以通過這個(gè)連接去訪問數(shù)據(jù)、執(zhí)行sql,
如下所示:
Driver driver = new com.mysql.cj.jdbc.Driver();
// 創(chuàng)建連接
Connection con = driver.connect(JDBC_URL, props);
Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery("show tables");
while (resultSet.next()) {
System.out.println(resultSet.getString(1));
}
con.close();池化技術(shù)
由于我們的代碼需要不斷與數(shù)據(jù)庫(kù)交互讀取數(shù)據(jù),如果每次請(qǐng)求數(shù)據(jù)都創(chuàng)建一個(gè)連接的話,網(wǎng)絡(luò)開銷是很大的,也會(huì)導(dǎo)致我們的程序比較慢,同時(shí)連接如果太多也會(huì)給數(shù)據(jù)庫(kù)造成壓力
為了解決這個(gè)問題,就有了池化技術(shù),把創(chuàng)建好的連接放在池里,用時(shí)去池里獲取,節(jié)省了創(chuàng)建連接的時(shí)間,也可以通過配置來限定池的最大連接數(shù)等

連接池最常用的工具基本就是阿里的Druid了,簡(jiǎn)單使用如下
// druid 數(shù)據(jù)源
DruidDataSource druidDataSource = new DruidDataSource();
// 數(shù)據(jù)源配置
druidDataSource.setUrl(JDBC_URL);
druidDataSource.setUsername(USERNAME);
druidDataSource.setPassword(PASSWORD);
// 初始化
druidDataSource.init();
// 獲取表名
Connection con = druidDataSource.getConnection();
Statement statement = con.createStatement();
ResultSet resultSet = statement.executeQuery("show tables");
while (resultSet.next()) {
System.out.println(resultSet.getString(1));
}
con.close();可以看到使用了Druid,獲取連接不再是直接使用驅(qū)動(dòng)創(chuàng)建連接,而是通過DruidDataSource對(duì)象獲取連接。
參數(shù)配置及說明
| 配置項(xiàng)名稱 | 缺省值 | 說明 | java set方法定義 |
|---|---|---|---|
| connectProperties | {} | map方式放入自定義的key和value,在Filter等地方可以獲取該信息進(jìn)行相應(yīng)邏輯控制 | public void com.alibaba.druid.pool.DruidDataSource.setConnectProperties(java.util.Properties) |
| connectionProperties | null | 字符串方式放入自定義的key和value,鍵值對(duì)用分號(hào)隔開,比如“a=b;c=d”,傳入空白字符串表示清空屬性,實(shí)際拆分字符串后賦值給connectProperties,在Filter等地方可以獲取該信息進(jìn)行相應(yīng)邏輯控制 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setConnectionProperties(java.lang.String) |
| connectTimeout | 0 | 新增的控制創(chuàng)建連接時(shí)的socket連接最大等待超時(shí),單位是毫秒,默認(rèn)0表示永遠(yuǎn)等待,工作原理是在創(chuàng)建連接時(shí)將該值設(shè)置到對(duì)應(yīng)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的屬性信息中由其JDBC驅(qū)動(dòng)進(jìn)行控制 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setConnectTimeout(int) |
| connectionInitSqls | [] | 數(shù)組方式定義物理連接初始化的時(shí)候執(zhí)行的1到多條sql語(yǔ)句,比如連接MySQL數(shù)據(jù)庫(kù)使用低版本驅(qū)動(dòng)的情況下,想使用utf8mb4,則可以配置sql為: set NAMES 'utf8mb4' | public void com.alibaba.druid.pool.DruidAbstractDataSource.setConnectionInitSqls(java.util.Collection) |
| createScheduler | null | 可以使用定時(shí)線程池方式異步創(chuàng)建連接,比起默認(rèn)的單線程創(chuàng)建連接方式,經(jīng)實(shí)際驗(yàn)證這種更可靠 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setCreateScheduler(java.util.concurrent.ScheduledExecutorService) |
| dbType | null | 對(duì)于不是Druid自動(dòng)適配支持的db類型,可以強(qiáng)制指定db類型,字符串值來自com.alibaba.druid.DbType的枚舉名 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setDbType(java.lang.String) |
| destroyScheduler | null | 可以使用定時(shí)線程池方式異步創(chuàng)建連接,比起默認(rèn)的單線程創(chuàng)建連接方式,經(jīng)實(shí)際驗(yàn)證這種更可靠 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setDestroyScheduler(java.util.concurrent.ScheduledExecutorService) |
| driverClassName | 根據(jù)url自動(dòng)識(shí)別 | 這一項(xiàng)可配可不配,如果不配置druid會(huì)根據(jù)url自動(dòng)識(shí)別dbType,然后選擇相應(yīng)的driverClassName | com.alibaba.druid.pool.DruidAbstractDataSource.setDriverClassName(String) |
| exceptionSorter | null | 當(dāng)數(shù)據(jù)庫(kù)拋出一些不可恢復(fù)的異常時(shí),拋棄連接 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setExceptionSorter(com.alibaba.druid.pool.ExceptionSorter) |
| failFast | false | null | public void com.alibaba.druid.pool.DruidAbstractDataSource.setFailFast(boolean) |
| filters | 屬性類型是逗號(hào)隔開的字符串,通過別名的方式配置擴(kuò)展插件,插件別名列表請(qǐng)參考druid jar包中的 /META-INF/druid-filter.properties,常用的插件有: 監(jiān)控統(tǒng)計(jì)用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall 防御sql注入的filter:wall | com.alibaba.druid.pool.DruidAbstractDataSource.setFilters(String) | |
| initialSize | 0 | 初始化數(shù)據(jù)源時(shí)建立物理連接的個(gè)數(shù)。初始化發(fā)生在顯示調(diào)用init方法,或者第一次getConnection時(shí) | public void com.alibaba.druid.pool.DruidAbstractDataSource.setInitialSize(int) |
| keepAlive | false | 連接池中的minIdle數(shù)量以內(nèi)的連接,空閑時(shí)間超過minEvictableIdleTimeMillis,則會(huì)執(zhí)行keepAlive操作。實(shí)際項(xiàng)目中建議配置成true | public void com.alibaba.druid.pool.DruidDataSource.setKeepAlive(boolean) |
| keepAliveBetweenTimeMillis | 120000 | null | public void com.alibaba.druid.pool.DruidAbstractDataSource.setKeepAliveBetweenTimeMillis(long) |
| logAbandoned | false | 在開啟removeAbandoned為true的情況,可以開啟該設(shè)置,druid在銷毀未及時(shí)關(guān)閉的連接時(shí),則會(huì)輸出日志信息,便于定位連接泄露問題 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setLogAbandoned(boolean) |
| loginTimeout | 單位是秒,底層調(diào)用DriverManager全局靜態(tài)方法 | java.sql.DriverManager.setLoginTimeout(int) | |
| maxActive | 8 | 連接池最大活躍連接數(shù)量,當(dāng)連接數(shù)量達(dá)到該值時(shí),再獲取新連接時(shí),將處于等待狀態(tài),直到有連接被釋放,才能借用成功 | public void com.alibaba.druid.pool.DruidDataSource.setMaxActive(int) |
| maxEvictableIdleTimeMillis | 25200000 | null | public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxEvictableIdleTimeMillis(long) |
| maxIdle | 8 | 已經(jīng)徹底廢棄,配置了也沒效果,以maxActive為準(zhǔn) | public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxIdle(int) |
| maxOpenPreparedStatements | 10 | null | public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxOpenPreparedStatements(int) |
| maxPoolPreparedStatementPerConnectionSize | 10 | 要啟用PSCache,必須配置大于0,當(dāng)大于0時(shí),poolPreparedStatements自動(dòng)觸發(fā)修改為true。在Druid中,不會(huì)存在Oracle下PSCache占用內(nèi)存過多的問題,可以把這個(gè)數(shù)值配置大一些,比如說100 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxPoolPreparedStatementPerConnectionSize(int) |
| maxWait | -1 | 獲取連接時(shí)最大等待時(shí)間,單位毫秒。配置了maxWait之后,缺省啟用公平鎖,并發(fā)效率會(huì)有所下降,如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setMaxWait(long) |
| minEvictableIdleTimeMillis | 1800000 | 連接保持空閑而不被驅(qū)逐的最小時(shí)間 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setMinEvictableIdleTimeMillis(long) |
| minIdle | 0 | 連接池最小空閑數(shù)量 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setMinIdle(int) |
| name | DataSource-**** | 配置這個(gè)屬性的意義在于,如果存在多個(gè)數(shù)據(jù)源,監(jiān)控的時(shí)候可以通過名字來區(qū)分開來。如果沒有配置,將會(huì)生成一個(gè)名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此屬性至少在1.0.5版本中是不起作用的,強(qiáng)行設(shè)置name會(huì)出錯(cuò)。 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setName(java.lang.String) |
| numTestsPerEvictionRun | 3 | 不再使用,已經(jīng)徹底廢棄,一個(gè)DruidDataSource只支持一個(gè)EvictionRun | public void com.alibaba.druid.pool.DruidAbstractDataSource.setNumTestsPerEvictionRun(int) |
| password | null | 連接數(shù)據(jù)庫(kù)的密碼。如果你不希望密碼直接寫在配置文件中,可以使用passwordCallback進(jìn)行配置,或者使用ConfigFilter。 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setPassword(java.lang.String) |
| passwordCallback | null | 可以自定義實(shí)現(xiàn)定制的PasswordCallback,然后實(shí)現(xiàn)定制的密碼解密效果 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setPasswordCallback(javax.security.auth.callback.PasswordCallback) |
| phyTimeoutMillis | -1 | 強(qiáng)制回收物理連接的最大超時(shí)時(shí)長(zhǎng),大于0的情況下才生效,當(dāng)物理創(chuàng)建之后存活的時(shí)長(zhǎng)超過該值時(shí),該連接會(huì)強(qiáng)制銷毀,便于重新創(chuàng)建新連接,建議可以配置成7小時(shí)的毫秒值,比如25200000,這樣可以規(guī)避MySQL的8小時(shí)連接斷開問題 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setPhyTimeoutMillis(long) |
| poolPreparedStatements | false | 是否緩存preparedStatement,也就是PSCache。PSCache對(duì)支持游標(biāo)的數(shù)據(jù)庫(kù)性能提升巨大,比如說oracle。在mysql下建議關(guān)閉。 | public void com.alibaba.druid.pool.DruidDataSource.setPoolPreparedStatements(boolean) |
| proxyFilters | 類型是List<com.alibaba.druid.filter.Filter>,如果同時(shí)配置了filters和proxyFilters,是組合關(guān)系,并非替換關(guān)系 | com.alibaba.druid.pool.DruidAbstractDataSource.setProxyFilters(List) | |
| queryTimeout | 0 | 控制查詢結(jié)果的最大超時(shí),單位是秒,大于0才生效,最終底層調(diào)用是java.sql.Statement.setQueryTimeout(int) | public void com.alibaba.druid.pool.DruidAbstractDataSource.setQueryTimeout(int) |
| removeAbandoned | false | 是否回收泄露的連接,默認(rèn)不開啟,建議只在測(cè)試環(huán)境設(shè)置未開啟,利用測(cè)試環(huán)境發(fā)現(xiàn)業(yè)務(wù)代碼中未正常關(guān)閉連接的情況 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setRemoveAbandoned(boolean) |
| removeAbandonedTimeoutMillis | 300000 | 開啟回收泄露連接的最大超時(shí),默認(rèn)300秒表示連接被借出超過5分鐘后,且removeAbandoned開啟的情況下,強(qiáng)制關(guān)閉該泄露連接 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setRemoveAbandonedTimeoutMillis(long) |
| socketTimeout | 0 | 新增的控制創(chuàng)建連接時(shí)的socket最大讀超時(shí),單位是毫秒,默認(rèn)0表示永遠(yuǎn)等待,配置成10000則表示db操作如果在10秒內(nèi)未返回應(yīng)答,將拋出異常,工作原理是在創(chuàng)建連接時(shí)將該值設(shè)置到對(duì)應(yīng)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的屬性信息中由其JDBC驅(qū)動(dòng)進(jìn)行控制 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setSocketTimeout(int) |
| testOnBorrow | false | 申請(qǐng)連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效,做了這個(gè)配置會(huì)降低性能,其實(shí)一般情況下都可以開啟,只有性能要求極其高且連接使用很頻繁的情況下才有必要禁用。 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setTestOnBorrow(boolean) |
| testOnReturn | false | 歸還連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效,做了這個(gè)配置會(huì)降低性能,這個(gè)一般不需要開啟。 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setTestOnReturn(boolean) |
| testWhileIdle | true | 建議配置為true,不影響性能,并且保證安全性。申請(qǐng)連接的時(shí)候檢測(cè),如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測(cè)連接是否有效。 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setTestWhileIdle(boolean) |
| timeBetweenEvictionRunsMillis | 60000 | 有兩個(gè)含義: 1) Destroy線程會(huì)檢測(cè)連接的間隔時(shí)間,如果連接空閑時(shí)間大于等于minEvictableIdleTimeMillis則關(guān)閉物理連接。 2) testWhileIdle的判斷依據(jù),詳細(xì)看testWhileIdle屬性的說明 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setTimeBetweenEvictionRunsMillis(long) |
| transactionQueryTimeout | 0 | 控制查詢結(jié)果的最大超時(shí),單位是秒,大于0才生效,最終是在開啟事務(wù)的情況下底層調(diào)用java.sql.Statement.setQueryTimeout(int) | public void com.alibaba.druid.pool.DruidAbstractDataSource.setTransactionQueryTimeout(int) |
| url | 連接數(shù)據(jù)庫(kù)的url,不同數(shù)據(jù)庫(kù)不一樣。例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto | com.alibaba.druid.pool.DruidAbstractDataSource.setUrl(String) | |
| username | null | 連接數(shù)據(jù)庫(kù)的用戶名 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setUsername(java.lang.String) |
| validationQuery | null | 用來檢測(cè)連接是否有效的sql,要求是一個(gè)查詢語(yǔ)句,常用select 'x'。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會(huì)起作用。 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setValidationQuery(java.lang.String) |
| validationQueryTimeout | -1 | 單位:秒,檢測(cè)連接是否有效的超時(shí)時(shí)間,大于0才生效。底層調(diào)用jdbc Statement對(duì)象的void setQueryTimeout(int seconds)方法 | public void com.alibaba.druid.pool.DruidAbstractDataSource.setValidationQueryTimeout(int) |
實(shí)際配置示例
Spring Boot 方式(推薦)
依賴
<!--引入druid數(shù)據(jù)源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>連接池配置:
spring:
datasource:
#數(shù)據(jù)源基本配置
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_crud
type: com.alibaba.druid.pool.DruidDataSource
#數(shù)據(jù)源其他配置
druid:
#配置初始化大小、最小、最大線程數(shù)
initialSize: 5
minIdle: 5
#CPU核數(shù)+1,也可以大些但不要超過20,數(shù)據(jù)庫(kù)加鎖時(shí)連接過多性能下降
maxActive: 20
# 最大等待時(shí)間,內(nèi)網(wǎng):800,外網(wǎng):1200(三次握手1s)
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
#配置一個(gè)連接在池中最大空間時(shí)間,單位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
# 設(shè)置從連接池獲取連接時(shí)是否檢查連接有效性,true檢查,false不檢查
testOnBorrow: true
# 設(shè)置從連接池歸還連接時(shí)是否檢查連接有效性,true檢查,false不檢查
testOnReturn: true
#可以支持PSCache(提升寫入、查詢效率)
poolPreparedStatements: true
#配置監(jiān)控統(tǒng)計(jì)攔截的filters,去掉后監(jiān)控界面sql無(wú)法統(tǒng)計(jì),'wall'用于防火墻
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500實(shí)現(xiàn)密碼加密
目前配置文件中配置的數(shù)據(jù)庫(kù)用戶名和密碼都是明文的,這在某些情況下是不被允許的,那正好druid可以對(duì)其進(jìn)行加密,按以下操作即可:
- 利用工具類生成加密后密碼和公鑰
public static void main(String[] args) throws Exception {
String password = "root123";
System.out.println("明文密碼: " + password);
String[] keyPair = ConfigTools.genKeyPair(512);
//私鑰
String privateKey = keyPair[0];
//公鑰
String publicKey = keyPair[1];
//用私鑰加密后的密文
password = ConfigTools.encrypt(privateKey, password);
System.out.println("privateKey:" + privateKey);
System.out.println("publicKey:" + publicKey);
System.out.println("password:" + password);
String decryptPassword = ConfigTools.decrypt(publicKey, password);
System.out.println("解密后:" + decryptPassword);
}
運(yùn)行后得到:

利用命令加密
java -cp D:/xxxx/druid-1.2.8/druid-1.2.8.jar com.alibaba.druid.filter.config.ConfigTools root java -cp D:/xxxx/druid-1.2.8/druid-1.2.8.jar com.alibaba.druid.filter.config.ConfigTools 123456
注:123456為你數(shù)據(jù)庫(kù)的密碼

對(duì)我們有用的是publicKey和加密后的password,這個(gè)publickey主要是用來解密的秘鑰
- 修改配置文件
用上面得到的密碼和publicKey替換配置文件中的密文:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKXfJyPsQ1rvSQXO+8m1TrIWS5XSSwzwDBIjPGZNbpZ10+Tai7k1GMzF6eufgMNWlNwOHJvxIYwjrts8b4UbSiECAwEAAQ==
druid:
url: jdbc:mysql://lcoahost:3306/test1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: ENC(EChlZH6XdPa129Ii3akF/92alTAIifYXdbFJaqKlmcQNF0a/QRoaAook16eO72vw4S4Ut8nXeoGOMdgFkQuW+A==)
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
#validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: true
url-pattern: /druid/*
#login-username: admin
#login-password: admin
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
config:
enabled: true
connection-properties: config.decrypt=true;config.decrypt.key=${spring.datasource.publicKey}配置文件跟加密相關(guān)的屬性
spring.datasource.druid.connection-properties
這個(gè)屬性配置的value是鍵值對(duì),其中config.decrypt=true表示要進(jìn)行解密,config.decrypt.key=${spring.datasource.publicKey}注入要解密需要的公鑰
spring.datasource.druid.filter.config.enabled=true
開啟configFilter, 這個(gè)不開啟是沒辦法進(jìn)行解密操作的
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java如何實(shí)現(xiàn)讀取txt文件內(nèi)容并生成Word文檔
本文主要介紹了通過Java實(shí)現(xiàn)讀取txt文件中的內(nèi)容,并將內(nèi)容生成Word文檔。文章的代碼非常詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2021-12-12
SpringBoot如何配置Controller實(shí)現(xiàn)Web請(qǐng)求處理
這篇文章主要介紹了SpringBoot如何配置Controller實(shí)現(xiàn)Web請(qǐng)求處理,文中通過圖解示例介紹的很詳細(xì),具有有一定的參考價(jià)值,需要的小伙伴可以參考一下2023-05-05
詳解Java的Struts2框架的結(jié)構(gòu)及其數(shù)據(jù)轉(zhuǎn)移方式
這篇文章主要介紹了詳解Java的Struts2框架的結(jié)構(gòu)及其數(shù)據(jù)轉(zhuǎn)移方式,Struts框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2016-01-01
Springboot整合easyexcel實(shí)現(xiàn)一個(gè)接口任意表的Excel導(dǎo)入導(dǎo)出
本文主要介紹了Springboot整合easyexcel實(shí)現(xiàn)一個(gè)接口任意表的Excel導(dǎo)入導(dǎo)出,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02
Spring?Security過濾器鏈加載執(zhí)行流程源碼解析
Spring?Boot?對(duì)于?Spring?Security?提供了自動(dòng)化配置方案,可以使用更少的配置來使用?Spring?Security。那么這個(gè)過濾器鏈?zhǔn)窃趺醇虞d和實(shí)現(xiàn)攔截的呢,對(duì)Spring?Security過濾器鏈加載執(zhí)行流程感興趣的朋友一起看看吧2021-12-12

