~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DRUID 简介
Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP、PROXOOL 等 DB 池的优点,同时加入了日志监控
Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池
《Spring Boot 默认数据源 HikariDataSource 与 JdbcTemplate》中已经介绍 Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源
本文承接《Spring Boot 默认数据源 HikariDataSource 与 JdbcTemplate》,重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控
配置参数
com.alibaba.druid.pool.DruidDataSource 基本配置参数如下:
配置 缺省值 说明
name 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。
如果没有配置,将会生成一个名字,格式是:"DataSource-" + System.identityHashCode(this)
jdbcUrl 连接数据库的url,不同数据库不一样。例如:
mysql : jdbc:mysql://10.20.153.104:3306/druid2
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username 连接数据库的用户名
password 连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter
driverClassName 根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)
initialSize 0 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive 8 最大连接池数量
maxIdle 8 已经不再使用,配置了也没效果
minIdle 最小连接池数量
maxWait 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatements false 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxOpenPreparedStatements -1 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
testOnBorrow true 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn false 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testWhileIdle false 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis 有两个含义:
1) Destroy线程会检测连接的间隔时间2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun 不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis
connectionInitSqls 物理连接初始化的时候执行的sql
exceptionSorter 根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接
filters 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:
监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
proxyFilters
类型是List
自定义数据源 Druid
引入数据源
第一步需要在应用的 pom.xml 文件中添加上 Druid 数据源依赖,而这个依赖可以从 Maven 仓库官网 Maven Repository 中获取
进入之后就可以选择需要的版本然后赋值进 pom.xml 文件中即可
切换 Druid 数据源
《Spring Boot 默认数据源 HikariDataSource 与 JdbcTemplate》中已经说过 Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源
但可以 通过 spring.datasource.type 指定数据源,可以从 Spring Boot 官方文档 查看
spring.datasource.type= # Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath.
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
数据源切换之后,同理可以注入 DataSource,然后获取到它,输出一看便知是否成功切换
package com.lct.www;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@RunWith(SpringRunner.class)
@SpringBootTest
public class HorseApplicationTests {
/**
* Spring Boot 默认已经配置好了数据源,程序员可以直接 DI 注入然后使用即可
*/
@Resource
DataSource dataSource;
@Test
public void contextLoads() throws SQLException {
System.out.println("数据源>>>>>>" + dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println("连接>>>>>>>>>" + connection);
System.out.println("连接地址>>>>>" + connection.getMetaData().getURL());
connection.close();
}
}
如下所示 数据源切换成功,Druid 数据源切换成功之后,便是要考虑设置它的参数,就如同以前 c3p0、dbcp 一样需要设置数据源连接初始化大小、最大连接数、等待时间、最小连接数、以及数据库监控 等等。
2018-08-20 08:54:08.276 INFO 8128 --- [ main] com.lct.www.HorseApplicationTests : Started HorseApplicationTests in 3.181 seconds (JVM running for 4.892)
数据源>>>>>>class com.alibaba.druid.pool.DruidDataSource
2018-08-20 08:54:08.523 INFO 8128 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
连接>>>>>>>>>com.mysql.jdbc.JDBC4Connection@7026b7ee
连接地址>>>>>jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
2018-08-20 08:54:08.897 INFO 8128 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@7e990ed7: startup date [Mon Aug 20 08:54:05 CST 2018]; root of context hierarchy
2018-08-20 08:54:08.904 INFO 8128 --- [ Thread-2] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed
Process finished with exit code 0
配置 Druid 数据源参数
如同以前 c3p0、dbcp 数据源可以设置数据源连接初始化大小、最大连接数、等待时间、最小连接数 等一样,Druid 数据源同理可以进行设置
Druid 数据源参数配置在全局配置文件中即可,如下所示:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#上半区公共部分对应的是 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 中的属性
#下半区属性对应的是 com.alibaba.druid.pool.DruidDataSource 中的属性,Spring Boot 默认是不注入不了这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
下半区 Druid 数据源的专有属性对应的是 com.alibaba.druid.pool.DruidDataSource 中的属性,虽然切换为 Druid 数据源之后,Spring Boot 会自动生成 DruidDataSource 并放入容器中供程序员使用,但是它并不会自动绑定配置文件的参
所以需要程序员自己为 com.alibaba.druid.pool.DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成了
如下所示,自己添加 DruidDataSource 组件到容器中,并绑定属性:
package com.lct.www.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* Created by Administrator on 2018/8/20 0020.
* Druid 数据源配置类
*/
@Configuration
public class DruidConfig {
/**
* 将自定义的 Druid 数据源添加到容器中,不再让 Spring Boot 自动创建
* 这样做的目的是:绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource
* 从而让它们生效
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中 前缀为 spring.datasource
* 的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*
* @return
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
对于 @ConfigurationProperties 绑定配置文件参数不熟悉时,可以参考《Spring Boot 全局配置文件》
现在可以获取容器中的 DataSource 转为 DruidDataSource ,然后取值看配置文件中的参数是否已经生效,也可以直接 Debug。
package com.lct.www;
import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@RunWith(SpringRunner.class)
@SpringBootTest
public class HorseApplicationTests {
/**
* Spring Boot 默认已经配置好了数据源,程序员可以直接 DI 注入然后使用即可
*/
@Resource
DataSource dataSource;
@Test
public void contextLoads() throws SQLException {
System.out.println("数据源>>>>>>" + dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println("连接>>>>>>>>>" + connection);
System.out.println("连接地址>>>>>" + connection.getMetaData().getURL());
DruidDataSource druidDataSource = (DruidDataSource) dataSource;
System.out.println("druidDataSource 数据源最大连接数:" + druidDataSource.getMaxActive());
System.out.println("druidDataSource 数据源初始化连接数:" + druidDataSource.getInitialSize());
connection.close();
}
}
控制台输出如下,可见配置参数已经生效:
2018-08-20 10:21:48.498 INFO 18284 --- [ main] com.lct.www.HorseApplicationTests : Started HorseApplicationTests in 3.494 seconds (JVM running for 4.763)
数据源>>>>>>class com.alibaba.druid.pool.DruidDataSource
log4j:WARN No appenders could be found for logger (druid.sql.Connection).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2018-08-20 10:21:48.921 INFO 18284 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
连接>>>>>>>>>com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@37d871c2
连接地址>>>>>jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
druidDataSource 数据源最大连接数:20
druidDataSource 数据源初始化连接数:5
2018-08-20 10:21:48.936 INFO 18284 --- [ Thread-2] o.s.w.c.s.GenericWebApplicationContext : Closing org.springframework.web.context.support.GenericWebApplicationContext@58e1d9d: startup date [Mon Aug 20 10:21:45 CST 2018]; root of context hierarchy
2018-08-20 10:21:48.948 INFO 18284 --- [ Thread-2] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed
Process finished with exit code 0
配置 Druid 数据源监控
配置一个 web 监控的 filter,因为使用的是内置 Servlet 容器,所以可以参考《 Web 项目 tiger 之13 注册 Servlet 三大组件之 Filter》
配置 Druid 后台管理 Servlet
Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提供了一个默认的 web 页面。
所以第一步需要设置 Druid 的后台管理页面,比如 登录账号、密码 等
配置一个管理后台的 Servlet,因为使用的是内置 Servlet 容器,所以可以参考《 Web 项目 tiger 之12 注册 Servlet 三大组件之 Servlet》
package com.lct.www.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2018/8/20 0020.
* Druid 数据源配置类
*/
@Configuration
public class DruidConfig {
/**
* 将自定义的 Druid 数据源添加到容器中,不再让 Spring Boot 自动创建
* 这样做的目的是:绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource
* 从而让它们生效
*
* @return
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中 前缀为 spring.datasource
* 的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
/**
* 配置 Druid 监控 之 管理后台的 Servlet
* 内置 Servler 容器时没有web.xml 文件,所以使用 Spring Boot 的注册 Servlet 方式
*/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),
"/druid/*");
/**
* loginUsername:Druid 后台管理界面的登录账号
* loginPassword:Druid 后台管理界面的登录密码
* allow:Druid 后台允许谁可以访问
* initParams.put("allow", "localhost"):表示只有本机可以访问
* initParams.put("allow", ""):为空或者为null时,表示允许所有访问
* deny:Druid 后台拒绝谁访问
* initParams.put("deny", "192.168.1.20");表示禁止此ip访问
*/
Map
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "123456");
initParams.put("allow", "");
/*initParams.put("deny", "192.168.1.20");*/
/** 设置初始化参数*/
bean.setInitParameters(initParams);
return bean;
}
}
这些参数可以在 com.alibaba.druid.support.http.StatViewServlet 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
运行应用,测试结果
配置 Druid web 监控 filter
这个过滤器的作用就是统计 web 应用请求中所有的数据库信息,比如 发出的 sql 语句,sql 执行的时间、请求次数、请求的 url 地址、以及seesion 监控、数据库表的访问次数 等等。
package com.lct.www.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2018/8/20 0020.
* Druid 数据源配置类
*/
@Configuration
public class DruidConfig {
/**
* 将自定义的 Druid 数据源添加到容器中,不再让 Spring Boot 自动创建
* 这样做的目的是:绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource
* 从而让它们生效
*
* @return
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中 前缀为 spring.datasource
* 的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
/**
* 配置 Druid 监控 之 管理后台的 Servlet
* 内置 Servler 容器时没有web.xml 文件,所以使用 Spring Boot 的注册 Servlet 方式
*/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),
"/druid/*");
/**
* loginUsername:Druid 后台管理界面的登录账号
* loginPassword:Druid 后台管理界面的登录密码
* allow:Druid 后台允许谁可以访问
* initParams.put("allow", "localhost"):表示只有本机可以访问
* initParams.put("allow", ""):为空或者为null时,表示允许所有访问
* deny:Druid 后台拒绝谁访问
* initParams.put("deny", "192.168.1.20");表示禁止此ip访问
*/
Map
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "123456");
initParams.put("allow", "");
/*initParams.put("deny", "192.168.1.20");*/
/** 设置初始化参数*/
bean.setInitParameters(initParams);
return bean;
}
/**
* 配置 Druid 监控 之 web 监控的 filter
* WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
*/
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
/** exclusions:设置哪些请求进行过滤排除掉,从而不进行统计*/
Map
initParams.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
/** "/*" 表示过滤所有请求*/
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
运行应用,可以往后台发一些请求,同时进行一些 数据库 sql 操作,测试结果效果如下:
---------------------
转载自:https://blog.csdn.net/wangmx1993328/article/details/81865153