Spring boot 数据库连接池
Posted xiaodujava
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring boot 数据库连接池相关的知识,希望对你有一定的参考价值。
文章目录
Spring boot 数据库连接池
上一节 Spring boot jdbcTemplate
源码
[源码地址]:(https://gitee.com/mayun_xiaodu/spring-boot-all)
Spring boot 数据库连接池
上一章节我们使用了jdbcTemplate 进行数据库的简单操作,这章我们给数据库连接添加上数据连接池。
springboot 默认数据库 Hikari
springboot 内置式默认支持HiKari 数据库连接池的;在 DataSourceConfiguration 配置类 中我可以看到
默认引入创建了HikariDatasource ; hikari 号称是 最快的数据库连接池,不过国内一般使用druid
/**
* Hikari DataSource configuration.
*/
@Configuration
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
matchIfMissing = true)
static class Hikari {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
springboot 已经自动装配了 HikarDataSource 数据源所以我们只需要在配置文件中配置下连接池信息即可;
配置文件中使用 spring.hikari 前缀进行数据库连接配置
spring:
application:
name: test-jdbcPool
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mytest?useSSL=false&charsetEncoding=utf8
driver-class-name: com.mysql.jdbc.Driver
hikari:
maximum-pool-size: 10 # 最大连接数
minimum-idle: 5 # 最小空闲数
connection-timeout: 2000 # 获取连接超时时间; 默认30s
pool-name: my-test-hikari # 连接池名称
idle-timeout: 600000 # 空闲超时时间;默认是十分钟;空闲时间超过设定时间则会被回收
auto-commit: true # 是否自动提交
max-lifetime: 1800000 # 最大存活时间,默认30分钟
# connection-test-query: SELECT 1 # 连接数据库后测试语句
validation-timeout: 1000 #
# schema: 设置模式,例如 postgresql 有模式这个概念
配置完以上后我们使用 jdbcTemplate 或者mybatis 等进行数据库操作的时候就会默认使用上HikarDataSource 进行数据库连接操作。
alibaba Druid 数据库连接池
简述
Druid是Java语言中综合最好的数据库连接池。Druid能够提供强大的监控和扩展功能;我们把springboot 默认的 数据库连接池 hikar 缓存Druid 。
使用 druid 数据库连接池的好处:
- 开源,国内活跃度高
- 性能好,国内号称是java里最好的数据库连接池
- 功能多,提供了 sql统计,sql过滤,数据库密码加密等功能
druid github 地址
使用:
添加pom 依赖
我们这里选用druid 提供的springboot starter
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.18</version>
</dependency>
配置连接池信息
配置文件中配置连接池信息
spring:
# 数据源配置
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mytest?useSSL=false&charsetEncoding=utf8
driver-class-name: com.mysql.jdbc.Driver
# 连接池配置
druid:
max-active: 10 # 最大活跃数量 默认8
min-idle: 2 # 最小空闲数 默认0
initial-size: 5 # 初始连接数
max-wait: 2000 # 获取连接最大等待时间 默认 -1
validation-query: select 1
validation-query-timeout: 5000
time-between-eviction-runs-millis: 2000 # 间隔多久进行检测需要关闭的空闲连接
min-evictable-idle-time-millis: 600000 # 配置连接在池中最小生存的时间
max-wait-thread-count: 20 # 最大等待线程数
集成依赖springboot durid starter 后springboot 就会自动装配了DruidDatasource,改变了jdbc操作数据使用的DataSource.
druid 自动装配类:
这里面创建了 DruidDataSourceWrapper() 其本身就是 DruidDatasource, 通过 注解@AutoConfigureBefore(DataSourceAutoConfiguration.class) 可知此配置类是在 DataSourceAutoConfiguration 之前生效,所以
优于springboot 默认创建的 hikarDatasource;
@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,
DruidStatViewServletConfiguration.class,
DruidWebStatFilterConfiguration.class,
DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);
@Bean(initMethod = "init")
@ConditionalOnMissingBean
public DataSource dataSource() {
LOGGER.info("Init DruidDataSource");
return new DruidDataSourceWrapper();
}
}
所以加入了 Druid 的依赖后 就会自动选择使用 druidDatasource 作为数据源的操作,即可直接使用。
druid 监控功能
durid 的监控统计也是非常好用的;durid 内置了比较多的 Filter ;对sql的执行,和过滤监控,url 的方法都进行了比较好的统计。
配置Filters 开启哪些filter
在 spring.datasource.druid.filters 中配置, 多个使用逗号隔开; druid 在springboot 配置文件中前缀都是 spring.datasource.druid 所以有些截图就不添加
# 配置filters ;
#内置了日志类型: log4j ,slf4j, log4j2; 用于日志打印
#监控统计: stat ;
#解密和配置远程配置文件: config
#防火墙: wall
filters: stat,slf4j,wall
开启监控UI页面 StatViewServlet
stat-view-servlet:
enabled: true
login-username: root # 监控页面登录名
login-password: 123456 # 监控页面密码
开启 监控页面后, 就可以登录监控页面
监控页面
访问路径: localhost:8181/druid 就可以观察到相关的
数据源 记录了我们的数据库连接信息
sql监控 监控执行过的sql 数量,执行时间, 并发数等
Sql防火墙 监控我们配置的wallFilter 信息;
配置慢sql 扫描
spring:
datasource:
druid:
filter:
stat: # 监控配置
enabled: true
db-type: mysql
# 慢sql配置
log-slow-sql: true
# sql 执行超过多少ms算慢sql
slow-sql-millis: 1000
慢sql会在日志中打印 ,以及监控页面中sql监控中显示
配置 sql日志打印
使用slf4j; 配置文件中filters中添加slf4j
filters: stat,slf4j,wall
编写logback日志配置文件, 配置druid.sql.Statement 的日志输出配置 进行日志的打印和输出到日志文件; 我这里只配置了输出到控制台
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--获取spirng配置信息-->
<springProperty name="APP" source="spring.application.name"/>
<!-- 日志颜色转换器 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<Target>System.out</Target>
<encoder>
<pattern>%clr(${APP}){magenta} -- %d{yyyy-MM-dd HH:mm:ss.SSS} %clr([%5level]) %blue([%10t]) %cyan(%40logger{39}) : %clr(%m) %n
</pattern>
</encoder>
</appender>
<logger name="com.xiaodu" additivity="false">
<level value="warn"/>
</logger>
<!--配置sql打印-->
<logger name="druid.sql.Statement" level="debug" additivity="false">
<appender-ref ref="console"/>
</logger>
<root>
<level value="info"/>
<appender-ref ref="console"/>
</root>
</configuration>
日志打印信息
test-jdbcPool -- 2021-04-13 10:49:36.940 [DEBUG] [http-nio-8181-exec-1] druid.sql.Statement : {conn-10005, pstmt-20005} created. insert into t_user(u_id,u_name,password,money,create_time) values(?,?,?,?,?)
test-jdbcPool -- 2021-04-13 10:49:36.940 [DEBUG] [http-nio-8181-exec-1] druid.sql.Statement : {conn-10005, pstmt-20005} Parameters : [e0b2ae8bfd23497f9d0d5fa59d450add, xiaodu, xiaodu, 123456, 2021-04-13 10:49:36.939]
test-jdbcPool -- 2021-04-13 10:49:36.940 [DEBUG] [http-nio-8181-exec-1] druid.sql.Statement : {conn-10005, pstmt-20005} Types : [VARCHAR, VARCHAR, VARCHAR, BIGINT, TIMESTAMP]
test-jdbcPool -- 2021-04-13 10:49:36.993 [DEBUG] [http-nio-8181-exec-1] druid.sql.Statement : {conn-10005, pstmt-20005} update executed. effort 1. 52.4484 millis. insert into t_user(u_id,u_name,password,money,create_time) values(?,?,?,?,?)
test-jdbcPool -- 2021-04-13 10:49:36.993 [DEBUG] [http-nio-8181-exec-1] druid.sql.Statement : {conn-10005, pstmt-20005} closed
配置sql防火墙 WallFilter
配置sql语句的检测,是否能进行一些危险的sql操作
spring:
datasource:
druid:
filter:
wall: # sql防火墙配置
enabled: true
db-type: mysql
config:
select-all-column-allow: false # 是否允许select *
delete-allow: false # 是否允许delete 语句
drop-table-allow: false # 是否允许 drop table 语句
alter-table-allow: false # 是否允许 alter table 语句
truncate-allow: false
update-where-alay-true-check: true # 检测update 语句是否条件永远为真
update-where-none-check: true # 检测update 语句是否没有 where 条件
delete-where-none-check: true # 检测delete 语句是否没有 where 条件
delete-where-alway-true-check: true # 检测delete 语句是否条件永远为真
配置web应用和URL监控 WebStatFilter
spring:
datasource:
druid:
# web应用 和URL 监控
web-stat-filter:
enabled: true
exclusions: /static/*,*.js,*.gif,*.jpg,*.css,*.ico,/druid/* # 排除url
配置ConfigFilter
configFilter 可以进行数据库信息配置文件的位置,通过file 或者http 进行获取;和数据库密码加密操作;
重点说下数据库密码加密; 数据库密码在配置文件中明文显示是很敏感的。
数据库密码加密
- 使用durid 提供的 工具类生成加密后的密码
public class TestConfigFilter {
public static void main(String[] args) throws Exception {
String[] arg = new String[]{"123456"}; // 你的密码
ConfigTools.main(arg);
}
}
控制台输出加密后的密码信息
2. 配置configFilter
- filters 中加上config
filters: stat,slf4j,wall,config
- 添加工具类生成的公钥
db:
publickey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI9GVgduCJuY7K0Do7fSyrR0AyF+9leXaE4NlDnyEm/ZBixDPZCTgZLsaGkXFhiJ/14m7J+Ai1sC7q2RWbIoZSMCAwEAAQ==
- 添加connection-properties 开启解密
spring:
datasource:
druid:
connection-properties: config.decrypt=true;config.decrypt.key=${db.publickey}
- 修改密码为加密后的密码
spring:
# 数据源配置
datasource:
username: root
password: XGsrLVwuuZJNCxZBJ5Q398P32SKDYYqL/MsqbAFAnIyd0X+SBcTQztWfZNm9D/GmRh4M95yP4ABd3WuA9EMUFA==
以上就是 configFIlter 对数据库密码加密的操作。
配置spring 监控
配置spring监控中 就会拦截指定的springbean ;在 监控页面的spring监控模块中显示 那些方法执行了那些sql, 耗时等信息。
这里简单以按照spring bean类型拦截监控为例。 其他例如通过正则, springbean id 请参考官网。
@Bean
public DruidStatInterceptor druidStatInterceptor() throws Exception {
DruidStatInterceptor druidStatInterceptor = new DruidStatInterceptor();
druidStatInterceptor.afterPropertiesSet();
return druidStatInterceptor;
}
@Bean
public BeanTypeAutoProxyCreator beanTypeAutoProxyCreator() {
BeanTypeAutoProxyCreator beanTypeAutoProxyCreator = new BeanTypeAutoProxyCreator();
beanTypeAutoProxyCreator.setTargetBeanType(UserController.class); // 拦截的目标
beanTypeAutoProxyCreator.setInterceptorNames("druidStatInterceptor"); // bean拦截器名称
return beanTypeAutoProxyCreator;
}
配置完后; 我们访问Usercontroller 类中的方法; 然后看ui页面 spring监控
其他方式参考官网wiki
扩展-通过spring 注解配置druid
也可以在配置类中配置相关的druid信息, 例如 datasource, druid提供的监控功能filter功能等。
/*-------------使用配置类配置druid相关信息-----------------*/
@Bean
public DruidDataSource dataSource(DataSourceProperties dataSourceProperties) throws SQLException {
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
dataSource.setFilters("slf4j,wall,stat");
dataSource.setMaxActive(5);
return dataSource;
}
@Bean
public WallFilter wallFilter() {
WallFilter wallFilter = new WallFilter();
wallFilter.setConfig(wallConfig());
wallFilter.setThrowException(true); // 对被认为是攻击的sql进行抛异常
wallFilter.setLogViolation(true); // 对被认为是攻击的sql进行error 输出
return wallFilter;
}
@Bean
public WallConfig wallConfig() {
WallConfig wallConfig = new WallConfig();
wallConfig.setDeleteWhereAlwayTrueCheck(true);
wallConfig.setUpdateWhereAlayTrueCheck(true);
wallConfig.setDeleteWhereNoneCheck(true);
wallConfig.setUpdateWhereNoneCheck(true);
return wallConfig;
}
@Bean
public StatFilter statFilter() {
StatFilter statFilter = new StatFilter();
statFilter.setDbType("mysql");
statFilter.setLogSlowSql(true);
statFilter.setSlowSqlMillis(2000);
return statFilter;
}
下一节 Spring boot restTemplate
以上是关于Spring boot 数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章