原创出处 http://www.iocoder.cn/Spring-Boot/datasource-pool/ 「芋道源码」
本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-19 目录。
1. 概述
在我们的项目中,数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中,主要是
- Druid ,为监控而生的数据库连接池。
- HikariCP ,号称性能最好的数据库连接池。
至于怎么选择,两者都非常优秀,不用过多纠结。
- Spring Boot 2.X 版本,默认采用 HikariCP 。
- 阿里大规模采用 Druid 。
当然,如下有一些资料,胖友可以阅读参考:
- 《Druid 连接池介绍》
- 《为什么 HikariCP 被号称为性能最好的 Java 数据库连接池,如何配置使用》
- 《alibaba/druid pool analysis》 ,一个小小的“撕逼”。
下面,我们来进行 HikariCP 和 Druid 的入门,会配置单数据源和多数据源情况下的连接池。
2. HikariCP 单数据源
示例代码对应仓库:lab-19-datasource-pool-hikaricp-single 。
在本小节,我们会使用配置一个数据源的 HikariCP 连接池。
艿艿:推荐入门后,可以看看 HikariCP 的文档:https://github.com/brettwooldridge/HikariCP/wiki 。
2.1 引入依赖
在 pom.xml 文件中,引入相关依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>lab-19-datasource-pool-hikaricp-single</artifactId>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
</project>
|
- 无需主动引入 HikariCP 的依赖。因为在 Spring Boot 2.X 中,
spring-boot-starter-jdbc 默认引入 com.zaxxer.HikariCP 依赖。
2.2 应用配置文件
在 application.yml 中,添加 HikariCP 配置,如下:
1 2 3 4 5 6 7 8 9 10 11
| spring: datasource: url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: root password: hikari: minimum-idle: 10 maximum-pool-size: 10
|
- 在
spring.datasource 配置项下,我们可以添加数据源的通用配置。
- 在
spring.datasource.hikari 配置项下,我们可以添加 HikariCP 连接池的自定义配置。然后 DataSourceConfiguration.Hikari 会自动化配置 HikariCP 连接池。
HikariCP 更多配置项,可以看看如下表格:s
FROM 《HikariCP 连接池及其在 Spring Boot 中的配置》
| 配置项 |
描述 |
构造器默认值 |
默认配置validate之后的值 |
validate重置 |
| autoCommit |
自动提交从池中返回的连接 |
true |
true |
- |
| connectionTimeout |
等待来自池的连接的最大毫秒数 |
SECONDS.toMillis(30) = 30000 |
30000 |
如果小于250毫秒,则被重置回30秒 |
| idleTimeout |
连接允许在池中闲置的最长时间 |
MINUTES.toMillis(10) = 600000 |
600000 |
如果idleTimeout+1秒>maxLifetime 且 maxLifetime>0,则会被重置为0(代表永远不会退出);如果idleTimeout!=0且小于10秒,则会被重置为10秒 |
| maxLifetime |
池中连接最长生命周期 |
MINUTES.toMillis(30) = 1800000 |
1800000 |
如果不等于0且小于30秒则会被重置回30分钟 |
| connectionTestQuery |
如果您的驱动程序支持JDBC4,我们强烈建议您不要设置此属性 |
null |
null |
- |
| minimumIdle |
池中维护的最小空闲连接数 |
-1 |
10 |
minIdle<0或者minIdle>maxPoolSize,则被重置为maxPoolSize |
| maximumPoolSize |
池中最大连接数,包括闲置和使用中的连接 |
-1 |
10 |
如果maxPoolSize小于1,则会被重置。当minIdle<=0被重置为DEFAULT_POOL_SIZE则为10;如果minIdle>0则重置为minIdle的值 |
| metricRegistry |
该属性允许您指定一个 Codahale / Dropwizard MetricRegistry 的实例,供池使用以记录各种指标 |
null |
null |
- |
| healthCheckRegistry |
该属性允许您指定池使用的Codahale / Dropwizard HealthCheckRegistry的实例来报告当前健康信息 |
null |
null |
- |
| poolName |
连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置 |
null |
HikariPool-1 |
- |
| initializationFailTimeout |
如果池无法成功初始化连接,则此属性控制池是否将 fail fast |
1 |
1 |
- |
| isolateInternalQueries |
是否在其自己的事务中隔离内部池查询,例如连接活动测试 |
false |
false |
- |
| allowPoolSuspension |
控制池是否可以通过JMX暂停和恢复 |
false |
false |
- |
| readOnly |
从池中获取的连接是否默认处于只读模式 |
false |
false |
- |
| registerMbeans |
是否注册JMX管理Bean(MBeans) |
false |
false |
- |
| catalog |
为支持 catalog 概念的数据库设置默认 catalog |
driver default |
null |
- |
| connectionInitSql |
该属性设置一个SQL语句,在将每个新连接创建后,将其添加到池中之前执行该语句。 |
null |
null |
- |
| driverClassName |
HikariCP将尝试通过仅基于jdbcUrl的DriverManager解析驱动程序,但对于一些较旧的驱动程序,还必须指定driverClassName |
null |
null |
- |
| transactionIsolation |
控制从池返回的连接的默认事务隔离级别 |
null |
null |
- |
| validationTimeout |
连接将被测试活动的最大时间量 |
SECONDS.toMillis(5) = 5000 |
5000 |
如果小于250毫秒,则会被重置回5秒 |
| leakDetectionThreshold |
记录消息之前连接可能离开池的时间量,表示可能的连接泄漏 |
0 |
0 |
如果大于0且不是单元测试,则进一步判断:(leakDetectionThreshold < SECONDS.toMillis(2) or (leakDetectionThreshold > maxLifetime && maxLifetime > 0),会被重置为0 . 即如果要生效则必须>0,而且不能小于2秒,而且当maxLifetime > 0时不能大于maxLifetime |
| dataSource |
这个属性允许你直接设置数据源的实例被池包装,而不是让HikariCP通过反射来构造它 |
null |
null |
- |
| schema |
该属性为支持模式概念的数据库设置默认模式 |
driver default |
null |
- |
| threadFactory |
此属性允许您设置将用于创建池使用的所有线程的java.util.concurrent.ThreadFactory的实例。 |
null |
null |
- |
| scheduledExecutor |
此属性允许您设置将用于各种内部计划任务的java.util.concurrent.ScheduledExecutorService实例 |
null |
null |
- |
2.3 Application
创建 Application.java 类,配置 @SpringBootApplication 注解即可。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| // Application.java
@SpringBootApplication public class Application implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired private DataSource dataSource;
public static void main(String[] args) { // 启动 Spring Boot 应用 SpringApplication.run(Application.class, args); }
@Override public void run(String... args) { try (Connection conn = dataSource.getConnection()) { // 这里,可以做点什么 logger.info("[run][获得连接:{}]", conn); } catch (SQLException e) { throw new RuntimeException(e); } }
}
|
通过实现 CommandLineRunner 接口,应用启动完成后,回调 #run(String... args) 方法,输出下 Connection 信息。执行日志如下:
1 2 3
| 2019-11-12 11:15:32.303 INFO 41198 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2019-11-12 11:15:32.472 INFO 41198 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2019-11-12 11:15:32.473 INFO 41198 --- [ main] c.i.s.lab19.datasourcepool.Application : [run][获得连接:HikariProxyConnection@1561745898 wrapping com.mysql.jdbc.JDBC4Connection@793138bd]
|
- 可以看到,HikariDataSource 成功初始化。
3. HikariCP 多数据源
示例代码对应仓库:lab-19-datasource-pool-hikaricp-multiple 。
在本小节,我们会使用配置两个数据源的 HikariCP 连接池。
3.1 引入依赖
和 「2.1 引入依赖」 是一致。
3.2 应用配置文件
在 application.yml 中,添加 HikariCP 配置,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| spring: # datasource 数据源配置内容 datasource: # 订单数据源配置 orders: url: jdbc:mysql://127.0.0.1:3306/test_orders?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: root password: # HikariCP 自定义配置,对应 HikariConfig 配置属性类 hikari: minimum-idle: 20 # 池中维护的最小空闲连接数,默认为 10 个。 maximum-pool-size: 20 # 池中最大连接数,包括闲置和使用中的连接,默认为 10 个。 # 用户数据源配置 users: url: jdbc:mysql://127.0.0.1:3306/test_users?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: root password: # HikariCP 自定义配置,对应 HikariConfig 配置属性类 hikari: minimum-idle: 15 # 池中维护的最小空闲连接数,默认为 10 个。 maximum-pool-size: 15 # 池中最大连接数,包括闲置和使用中的连接,默认为 10 个。
|
- 我们在
spring.datasource 配置项下,定义了 orders 和 users 两个数据源的配置。而每个数据源的配置,和我们在 「2.2 应用配置文件」 是一致的。
3.3 数据源配置类
3.3.1 错误的示例
在网上,我们会看到这样配置多个数据源的配置类。代码如下:
1 2 3 4 5 6 7 8 9 10 11
| @Bean(name = "ordersDataSource") @ConfigurationProperties(prefix = "spring.datasource.orders") public DataSource ordersDataSource() { return DataSourceBuilder.create().build(); }
@Bean(name = "usersDataSource") @ConfigurationProperties(prefix = "spring.datasource.users") public DataSource ordersDataSource() { return DataSourceBuilder.create().build(); }
|
实际上,这样做的话,在部分场景下,会存在问题,这是为什么呢?
我们先来理解这段程序的用途。以 #ordersDataSource() 方法为例子:
DataSourceBuilder.create().build() 代码段,会创建一个 DataSource 数据源。
- 搭配上
@Bean(name = "ordersDataSource") 注解,会创建一个名字为 "ordersDataSource" 的 DataSource Bean 。这里,我们使用 HikariCP ,所以返回的是 HikariDataSource Bean 。
@ConfigurationProperties(prefix = "spring.datasource.orders") 注解,会将 "spring.datasource.orders" 配置项,逐个属性赋值给 DataSource Bean 。
看起来貌似没问题,但是如果每个数据源如果有 HikariCP 的 "hikari" 自定义配置项时,它的自定义配置项无法设置到 HikariDataSource Bean 中。因为,"spring.datasource.orders.hikari" 是 "spring.datasource.orders" 的第二层属性。而 HikariDataSource 的配置属性在第一层,这就导致无法正确的设置。
虽然存在该问题,但是大多数项目,我们并不会自定义 HikariCP 的 "hikari" 配置项,所以这个问题就偷偷藏起来,“不存在”了。
3.3.2 正确的示例
当然,作为入门的示例,艿艿还是希望提供正确的做法。
在 cn.iocoder.springboot.lab19.datasourcepool.config 包路径下,我们会创建 DataSourceConfig 配置类。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
@Configuration public class DataSourceConfig {
@Primary @Bean(name = "ordersDataSourceProperties") @ConfigurationProperties(prefix = "spring.datasource.orders") public DataSourceProperties ordersDataSourceProperties() { return new DataSourceProperties(); }
@Bean(name = "ordersDataSource") @ConfigurationProperties(prefix = "spring.datasource.orders.hikari") public DataSource ordersDataSource() { DataSourceProperties properties = this.ordersDataSourceProperties(); return createHikariDataSource(properties); }
@Bean(name = "usersDataSourceProperties") @ConfigurationProperties(prefix = "spring.datasource.users") public DataSourceProperties usersDataSourceProperties() { return new DataSourceProperties(); }
@Bean(name = "usersDataSource") @ConfigurationProperties(prefix = "spring.datasource.users.hikari") public DataSource usersDataSource() { DataSourceProperties properties = this.usersDataSourceProperties(); return createHikariDataSource(properties); }
private static HikariDataSource createHikariDataSource(DataSourceProperties properties) { HikariDataSource dataSource = properties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); if (StringUtils.hasText(properties.getName())) { dataSource.setPoolName(properties.getName()); } return dataSource; }
}
|
这块代码,我们是参考 Spring Boot DataSourceConfiguration.Hikari 配置类来实现的。
#ordersDataSourceProperties() 方法,创建 "orders" 数据源的 DataSourceProperties 配置对象。
@Primary 注解,保证项目中有一个主的 DataSourceProperties Bean 。
new DataSourceProperties() 代码段,会创建一个 DataSourceProperties 数据源的配置对象。
- 搭配上
@Bean(name = "ordersDataSourceProperties") 注解,会创建一个名字为 "ordersDataSourceProperties" 的 DataSourceProperties Bean 。
@ConfigurationProperties(prefix = "spring.datasource.orders") 注解,会将 "spring.datasource.orders" 配置项,逐个属性赋值给 DataSourceProperties Bean 。
#ordersDataSource() 方法,创建 orders 数据源。
<1.1> 处,调用 #ordersDataSourceProperties() 方法,获得 orders 数据源的 DataSourceProperties 。
<1.2> 处,调用 #createHikariDataSource(DataSourceProperties properties)方法,创建 HikariDataSource 对象。这样,"spring.datasource.orders" 配置项,逐个属性赋值给 HikariDataSource Bean 。
- 搭配上
@Bean(name = "ordersDataSource") 注解,会创建一个名字为 "ordersDataSource" 的 HikariDataSource Bean 。
@ConfigurationProperties(prefix = "spring.datasource.orders.hikari") 注解,会将 HikariCP 的 "spring.datasource.orders.hikari" 自定义配置项,逐个属性赋值给 HikariDataSource Bean 。
users 数据源的配置,同上,就不重复解释了。
3.4 Application
创建 Application.java 类,配置 @SpringBootApplication 注解即可。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
@SpringBootApplication public class Application implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(Application.class);
@Resource(name = "ordersDataSource") private DataSource ordersDataSource;
@Resource(name = "usersDataSource") private DataSource usersDataSource;
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
@Override public void run(String... args) { try (Connection conn = ordersDataSource.getConnection()) { logger.info("[run][ordersDataSource 获得连接:{}]", conn); } catch (SQLException e) { throw new RuntimeException(e); }
try (Connection conn = usersDataSource.getConnection()) { logger.info("[run][usersDataSource 获得连接:{}]", conn); } catch (SQLException e) { throw new RuntimeException(e); } }
}
|
执行日志如下:
1 2 3 4 5 6
| 2019-11-12 15:30:35.060 INFO 45868 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2019-11-12 15:30:35.365 INFO 45868 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2019-11-12 15:30:35.367 INFO 45868 --- [ main] c.i.s.lab19.datasourcepool.Application : [run][ordersDataSource 获得连接:HikariProxyConnection@1041547629 wrapping com.mysql.jdbc.JDBC4Connection@3c989952] 2019-11-12 15:30:35.371 INFO 45868 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Starting... 2019-11-12 15:30:35.376 INFO 45868 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Start completed. 2019-11-12 15:30:35.376 INFO 45868 --- [ main] c.i.s.lab19.datasourcepool.Application : [run][usersDataSource 获得连接:HikariProxyConnection@795748540 wrapping com.mysql.jdbc.JDBC4Connection@7c098bb3]
|
- 可以看到,两个 HikariDataSource 成功初始化。
多数据源和 JPA、MyBatis、JdbcTemplate 的集成,可以看看 《芋道 Spring Boot 多数据源(读写分离)入门》 文章。
4. Druid 单数据源
示例代码对应仓库:lab-19-datasource-pool-druid-single 。
在本小节,我们会使用配置一个数据源的 Druid 连接池。并简单看看 Druid 的监控功能。
艿艿:推荐入门后,可以看看 Druid 的文档:https://github.com/alibaba/druid/wiki/ 。
4.1 引入依赖
在 pom.xml 文件中,引入相关依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>lab-19-datasource-pool-druid-single</artifactId>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.21</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
</project>
|
具体每个依赖的作用,胖友自己认真看下艿艿添加的所有注释噢。S
4.2 应用配置文件
在 application.yml 中,添加 Druid 配置,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| spring: datasource: url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: root password: type: com.alibaba.druid.pool.DruidDataSource druid: min-idle: 0 max-active: 20 filter: stat: log-slow-sql: true slow-sql-millis: 5000 stat-view-servlet: enabled: true login-username: yudaoyuanma login-password: javaniubi
|
spring.datasource 配置项,设置 Spring 数据源的通用配置。其中,spring.datasource.type 配置项,需要主动设置使用 DruidDataSource 。因为默认情况下,spring-boot-starter-jdbc 的 DataSourceBuilder 会按照 DATA_SOURCE_TYPE_NAMES 的顺序,尝试推断数据源的类型。
spring.datasource.druid 配置项,设置 Druid 连接池的自定义配置。然后 DruidDataSourceAutoConfigure 会自动化配置 Druid 连接池。
- 在 《Druid —— 配置属性》 和 《DruidDataSource 配置属性列表》 下,提供了各种 Druid 的配置项,胖友可以自己看看。
filter.stat 配置项,我们配置了 Druid StatFilter ,用于统计监控信息。对应文档 《Druid —— 配置_StatFilter》 。要注意,StatFilter 并不是我们说的 javax.servlet.Filter ,而是 Druid 提供的 Filter 拓展机制。
filter.stat-view-servlet 配置项,我们配置了 Druid StatViewServlet ,用于提供监控信息的展示的 html 页面和 JSON API 。对应文档 《Druid —— 配置_StatViewServlet 配置》 。StatViewServlet 就是我们说的 javax.servlet.Filter。
4.3 Application
创建 Application.java 类,配置 @SpringBootApplication 注解即可。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @SpringBootApplication public class Application implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired private DataSource dataSource;
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
@Override public void run(String... args) { logger.info("[run][获得数据源:{}]", dataSource.getClass()); }
}
|
执行日志如下:
1 2 3 4
| 2019-11-12 19:34:12.079 INFO 48359 --- [ main] c.a.d.s.b.a.DruidDataSourceAutoConfigure : Init DruidDataSource 2019-11-12 19:34:12.156 INFO 48359 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
2019-11-12 19:34:12.560 INFO 48359 --- [ main] c.i.s.lab19.datasourcepool.Application : [run][获得数据源:class com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper]
|
- 可以看到,DruidDataSource 成功初始化。
4.4 监控功能
因为我们在 「4.2 应用配置中」 中,做了如下操作:
- 通过
spring.datasource.filter.stat 配置了 StatFilter ,统计监控信息。
- 通过
spring.datasource.filter.stat-view-servlet 配置了 StatViewServlet ,提供监控信息的展示的 html 页面和 JSON API 。
所以我们在启动项目后,访问 http://127.0.0.1:8080/druid 地址,可以看到监控 html 页面。如下图所示:
在界面的顶部,提供了数据源、SQL 监控、SQL 防火墙等等功能。
每个界面上,可以通过 View JSON API 获得数据的来源。同时,我们可以在 JSON API( http://127.0.0.1:8080/druid/api.html ) 菜单对应的界面中,看到 StatViewServlet 内置的监控信息的 JSON API 列表。
因为监控信息是存储在 JVM 内存中,在 JVM 进程重启时,信息将会丢失。如果我们希望持久化到 MySQL、Elasticsearch、HBase 等存储器中,可以通过 StatViewServlet 提供的 JSON API 接口,采集监控信息。另外,有个 druid-aggregated-monitor 开源项目,提供了 集中监控分布式服务中的 Druid 连接池的方案和思路。
如果 StatViewServlet 提供的 JSON API 接口,无法满足我们的诉求,我们可以通过自定义 API 接口,使用 DruidStatManagerFacade 获得监控信息。使用示例 DruidStatController 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@RestController public class DruidStatController {
@GetMapping("/monitor/druid/stat") @Deprecated public Object druidStat(){ return DruidStatManagerFacade.getInstance().getDataSourceStatDataList(); }
}
|
当然,绝大多数情况下,我们并不需要做这方面的拓展。
5. Druid 多数据源
示例代码对应仓库:lab-19-datasource-pool-druid-multiple 。
在本小节,我们会使用配置两个数据源的 Druid 连接池。
5.1 引入依赖
和 「4.1 引入依赖」 是一致。
5.2 应用配置
在 application.yml 中,添加 Druid 配置,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| spring: datasource: orders: url: jdbc:mysql://127.0.0.1:3306/test_orders?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: root password: type: com.alibaba.druid.pool.DruidDataSource min-idle: 0 max-active: 20 users: url: jdbc:mysql://127.0.0.1:3306/test_users?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: root password: type: com.alibaba.druid.pool.DruidDataSource min-idle: 0 max-active: 20 druid: filter: stat: log-slow-sql: true slow-sql-millis: 5000 stat-view-servlet: enabled: true login-username: yudaoyuanma login-password: javaniubi
|
- 不同于我们在 「3.2 应用配置文件」 中,我们将 Druid 的自定义配置,和
url、driver-class-name 等数据源的通用配置放在同一级,这样后续我们只需要使用 @ConfigurationProperties(prefix = "spring.datasource.orders") 的方式,就能完成 DruidDataSource 的配置属性设置。
- 在
spring.datasource.druid 配置项下,我们还是配置了 filter.stat 和 stat-view-servlet 配置项,用于 Druid 监控功能。
5.3 数据源配置类
在 cn.iocoder.springboot.lab19.datasourcepool.config 包路径下,我们会创建 DataSourceConfig 配置类。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
@Configuration public class DataSourceConfig {
@Primary @Bean(name = "ordersDataSource") @ConfigurationProperties(prefix = "spring.datasource.orders") public DataSource ordersDataSource() { return DruidDataSourceBuilder.create().build(); }
@Bean(name = "usersDataSource") @ConfigurationProperties(prefix = "spring.datasource.users") public DataSource usersDataSource() { return DruidDataSourceBuilder.create().build(); }
}
|
- 因为我们在 「5.2 应用配置」 中,将 Druid 自定义的配置项,和数据源的通用配置放在了同一级,所以我们只需使用
@ConfigurationProperties(prefix = "spring.datasource.orders") 这样的方式即可。
- 当然,「3.3.2 正确的示例」 也是可以这么做的。实际情况下,比较推荐本小节的方式。
5.4 Application
创建 Application.java 类,配置 @SpringBootApplication 注解即可。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
@SpringBootApplication public class Application implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(Application.class);
@Resource(name = "ordersDataSource") private DataSource ordersDataSource;
@Resource(name = "usersDataSource") private DataSource usersDataSource;
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
@Override public void run(String... args) { logger.info("[run][获得数据源:{}]", ordersDataSource.getClass());
logger.info("[run][获得数据源:{}]", usersDataSource.getClass()); }
}
|
执行日志如下:
1 2
| 2019-11-12 21:39:24.063 INFO 49670 --- [ main] c.i.s.lab19.datasourcepool.Application : [run][获得数据源:class com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper] 2019-11-12 21:39:24.064 INFO 49670 --- [ main] c.i.s.lab19.datasourcepool.Application : [run][获得数据源:class com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceWrapper]
|
- 可以看到,两个 DruidDataSource 成功初始化。
5.5 监控功能
和 「4.4 监控功能」 一致。
不过呢,我们在监控页面上,可以看到两个 Druid 数据库连接池。