1. 什么是Druid连接池
Druid连接池是阿里巴巴开源的数据库连接池项目。Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能。功能强大,能防SQL注入,内置Loging能诊断Hack应用行为。
虽然 HikariCP 的速度稍快,但是,Druid能够提供强大的监控和扩展功能,也是阿里巴巴的开源项目。
Spring Boot 2.x 默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源。
stat:Druid内置提供一个StatFilter,用于统计监控信息。
wall:Druid防御SQL注入攻击的WallFilter就是通过Druid的SQL Parser分析。Druid提供的SQL Parser可以在JDBC层拦截SQL做相应处理,比如说分库分表、审计等。
log4j2:这个就是 日志记录的功能,可以把sql语句打印到log4j2 供排查问题。
2. 添加依赖
```xml
com.alibaba druid-spring-boot-starter ${com.alibaba.druid.version}
<a name="cZ9Gm"></a>
# 3. 配置相关属性
1. **配置Druid数据源(连接池):** 如同以前 c3p0、dbcp 数据源可以设置数据源连接初始化大小、最大连接数、等待时间、最小连接数 等一样,Druid 数据源同理可以进行设置;
1. **配置 Druid web 监控 filter(WebStatFilter):** 这个过滤器的作用就是统计 web 应用请求中所有的数据库信息,比如 发出的 sql 语句,sql 执行的时间、请求次数、请求的 url 地址、以及seesion 监控、数据库表的访问次数 等等。
1. **配置 Druid 后台管理 Servlet(StatViewServlet):** Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提供了一个默认的 web 页面;需要设置 Druid 的后台管理页面的属性,比如 登录账号、密码 等;
Druid Spring Boot Starter 配置属性的名称完全遵照 Druid,可以通过 Spring Boot 配置文件来配置Druid数据库连接池和监控,如果没有配置则使用默认值。
```java
# 服務器HTTP端口,默認:8080
server.port=8088
# 應用程序的上下文路徑
server.servlet.context-path=/
# 會話超時。 如果未指定持續時間後綴,則將使用秒。默認30m
server.servlet.session.timeout=30m
# 用於解碼URI的字符編碼,默認:UTF-8
server.tomcat.uri-encoding=UTF-8
# Tomcat基本目錄。 如果未指定,則使用一個臨時目錄。
server.tomcat.basedir=target/temp
# 服務器在任何給定時間接受和處理的最大連接數。 一旦達到限制,操作系統仍然可以基於“ acceptCount”屬性接受連接。默認 8192
server.tomcat.max-connections=2000
# 工作線程的最大數量。默認:200
server.tomcat.threads.max=200
# 連接器在接受連接後將等待呈現請求URI行的時間。
server.tomcat.connection-timeout=8000
#datasource
# 連接資料庫的url,不同資料庫不一樣。
spring.datasource.druid.url=jdbc:postgresql://10.213.133.130:5432/zbdb
# 連接資料庫的用戶名
spring.datasource.druid.username=lgszz
# 連接資料庫的密碼。
spring.datasource.druid.password=lgszz.2020
# druid 配置
# 要使用的連接池實現的完全限定名稱。 默認情況下,它是從類路徑中自動檢測到的。
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 初始化時建立物理連接的個數。初始化發生在顯示調用init方法,或者第一次getConnection時
spring.datasource.druid.initial-size=10
# 最大連接池數量
spring.datasource.druid.max-active=50
# 最小連接池數量
spring.datasource.druid.min-idle=10
# 獲取連接時最大等待時間,單位毫秒。配置了maxWait之後,缺省啟用公平鎖,併發效率會有所下降,如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。
spring.datasource.druid.max-wait=3000
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 配置一個連接在池中最小生存的時間,單位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000
# 用來檢測連接是否有效的sql,要求是一個查詢語句,常用select 'x'。如果validation-query為null,test-on-borrow、test-on-return、test-while-idle都不會起作用。
spring.datasource.druid.validation-query=SELECT 1
# 建議配置為true,不影響性能,並且保證安全性。申請連接的時候檢測,如果閒置時間大於time-between-eviction-runs-millis,執行validation-query檢測連接是否有效。默認爲false
spring.datasource.druid.test-while-idle=true
# 申請連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能。默認爲true
spring.datasource.druid.test-on-borrow=true
# 歸還連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能。默認爲false
spring.datasource.druid.test-on-return=false
# 是否緩存preparedStatement,也就是PSCache。PSCache對支援游標的資料庫性能提升巨大,比如說oracle。在mysql下建議關閉。
spring.datasource.druid.pool-prepared-statements=true
# 要啟用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改為true。
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=50
# 連接池中的minIdle數量以內的連接,閒置時間超過minEvictableIdleTimeMillis,則會執行keepAlive操作
#spring.datasource.druid.keep-alive=true
# Spring 監控,利用aop 對指定介面的執行時間,jdbc數進行記錄
#spring.datasource.druid.aop-patterns="com.springboot.template.dao.*"
########### 啟用內置篩檢程式(第一個 stat必須,否則監控不到SQL)##########
# 配置監控統計攔截的filters,去掉後監控介面SQL無法進行統計,屬性類型是字串,通過別名的方式配置擴展外掛程式,常用的外掛程式有:監控統計用的filter:stat,日誌用的filter:log4j,防禦sql注入的filter:wall
spring.datasource.druid.filters=config,stat,slf4j,wall
# 開啟druid datasource 的狀態監控
spring.datasource.druid.filter.stat.enabled=true
# 開啟慢sql監控,超過2s 就認為是慢sql,記錄到日誌中
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000
# 配置 connection-properties,啓用加密
#spring.datasource.druid.connection-properties=config.decrypt=true;
# 啓用ConfigFilter
#spring.datasource.druid.filter.config.enabled=true
########## druid連接池監控 ##########
########## 配置StatViewServlet(監控頁面),用於展示Druid的統計信息 ##########
# 啓用StatViewServlet
spring.datasource.druid.stat-view-servlet.enabled=true
# 訪問內置監控頁面的路徑,內置監控頁面的首頁是/druid/index.html
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
# 不允許清空統計資料,重新計算
spring.datasource.druid.stat-view-servlet.reset-enable=false
# 配置監控頁面訪問賬號
spring.datasource.druid.stat-view-servlet.login-username=admin
# 配置監控頁面訪問密碼
spring.datasource.druid.stat-view-servlet.login-password=admin
# 白名單,允許訪問的位址,如果allow沒有配置或者為空,則允許所有訪問
spring.datasource.druid.stat-view-servlet.allow=
# 黑名單,拒絕訪問的位址,deny優先於allow,如果在deny列表中,就算在allow列表中,也會被拒絕
spring.datasource.druid.stat-view-servlet.deny=
########## 配置WebStatFilter,用於採集web關聯監控的數據 ##########
# 啓用StatFilter
spring.datasource.druid.web-stat-filter.enabled=true
# 過濾所有url
spring.datasource.druid.web-stat-filter.url-pattern=/*
# 排除一些不必要的url
spring.datasource.druid.web-stat-filter.exclusions=*.gif,*.png,*.jpg,*.html,*.js,*.css,*.ico,/druid/*
# 開啓session統計功能
spring.datasource.druid.web-stat-filter.session-stat-enable=true
# session的最大個數,默認1000
spring.datasource.druid.web-stat-filter.session-stat-max-count=1000
述配置文件的参数可以在 com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties 和 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties中找到
3.1 如何配置 Filter
可以通过 spring.datasource.druid.filters=stat,wall,log4j ...
的方式来启用相应的内置Filter,不过这些Filter都是默认配置。如果默认配置不能满足需求,可以放弃这种方式,通过配置文件来配置Filter,下面是例子。
# 配置StatFilter
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.db-type=h2
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000
# 配置WallFilter
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.filter.wall.db-type=h2
spring.datasource.druid.filter.wall.config.delete-allow=false
spring.datasource.druid.filter.wall.config.drop-table-allow=false
目前为以下 Filter 提供了配置支持,根据(spring.datasource.druid.filter.*)进行配置。
StatFilter
WallFilter
ConfigFilter
EncodingConvertFilter
Slf4jLogFilter
Log4jFilter
Log4j2Filter
CommonsLogFilter
不想使用内置的 Filters,要想使自定义 Filter 配置生效需要将对应 Filter 的 enabled 设置为 true ,Druid Spring Boot Starter 默认禁用 StatFilter,可以将其 enabled 设置为 true 来启用它。
4. 监控页面
- 启动项目后,访问
/druid/login.html
来到登录页面,输入用户名密码登录 - 数据源页面 是当前DataSource配置的基本信息,上述配置的Filter可以在里面找到,如果没有配置Filter(一些信息会无法统计,例如“SQL监控”,会无法获取JDBC相关的SQL执行信息)
- SQL监控页面,统计了所有SQL语句的执行情况
- URL监控页面,统计了所有Controller接口的访问以及执行情况
- Spring 监控页面,利用aop 对指定接口的执行时间,jdbc数进行记录
- SQL防火墙页面,druid提供了黑白名单的访问,可以清楚的看到sql防护情况。
- Session监控页面,可以看到当前的session状况,创建时间、最后活跃时间、请求次数、请求时间等详细参数。
JSONAPI 页面,通过api的形式访问Druid的监控接口,api接口返回Json形式数据。
5. sql监控
配置 Druid web 监控 filter(
WebStatFilter
)这个过滤器,作用就是统计 web 应用请求中所有的数据库信息,比如 发出的 sql 语句,sql 执行的时间、请求次数、请求的 url 地址、以及seesion 监控、数据库表的访问次数 等等。########## 配置WebStatFilter,用於採集web關聯監控的數據 ##########
# 啓用StatFilter
spring.datasource.druid.web-stat-filter.enabled=true
# 過濾所有url
spring.datasource.druid.web-stat-filter.url-pattern=/*
# 排除一些不必要的url
spring.datasource.druid.web-stat-filter.exclusions=*.gif,*.png,*.jpg,*.html,*.js,*.css,*.ico,/druid/*
# 開啓session統計功能
spring.datasource.druid.web-stat-filter.session-stat-enable=true
# session的最大個數,默認1000
spring.datasource.druid.web-stat-filter.session-stat-max-count=1000
6. 慢sql记录
有时候,系统中有些SQL执行很慢,我们希望使用日志记录下来,可以开启Druid的慢SQL记录功能
# 開啟druid datasource 的狀態監控
spring.datasource.druid.filter.stat.enabled=true
# 開啟慢sql監控,超過2s 就認為是慢sql,記錄到日誌中
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000
7. spring 监控
访问之后spring监控默认是没有数据的;
这需要导入SprngBoot的AOP的Starter<!--SpringBoot 的aop 模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
需要在 application.properties 配置:
Spring监控AOP切入点,如com.springboot.template.dao.*,配置多个英文逗号分隔spring.datasource.druid.aop-patterns="com.springboot.template.dao.*"
8. 去 Ad(广告)
访问监控页面的时候,你可能会在页面底部(footer)看到阿里巴巴的广告
原因:引入的druid的jar包中的common.js
(里面有一段js代码是给页面的footer追加广告的)
如果想去掉,有两种方式:8.1 直接手动注释这段代码
如果是使用Maven,直接到本地仓库中,查找这个jar包
要注释的代码:// this.buildFooter();
common.js的位置:
com/alibaba/druid/1.1.23/druid-1.1.23.jar!/support/http/resources/js/common.js
8.2 使用过滤器过滤
注册一个过滤器,过滤common.js的请求,使用正则表达式替换相关的广告内容 ```java @Configuration @ConditionalOnWebApplication @AutoConfigureAfter(DruidDataSourceAutoConfigure.class) @ConditionalOnProperty(name = “spring.datasource.druid.stat-view-servlet.enabled”, havingValue = “true”, matchIfMissing = true) public class RemoveDruidAdConfig {
/**
- 方法名: removeDruidAdFilterRegistrationBean
- 方法描述 除去页面底部的广告
- @param properties com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties
@return org.springframework.boot.web.servlet.FilterRegistrationBean */ @Bean public FilterRegistrationBean removeDruidAdFilterRegistrationBean(DruidStatProperties properties) {
// 获取web监控页面的参数 DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); // 提取common.js的配置路径 String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : “/druid/“; String commonJsPattern = pattern.replaceAll(“\“, “js/common.js”);
final String filePath = “support/http/resources/js/common.js”;
//创建filter进行过滤 Filter filter = new Filter() {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
// 重置缓冲区,响应头不会被重置
response.resetBuffer();
// 获取common.js
String text = Utils.readFromResource(filePath);
// 正则替换banner, 除去底部的广告信息
text = text.replaceAll("<a.*?banner\"></a><br/>", "");
text = text.replaceAll("powered.*?shrek.wang</a>", "");
response.getWriter().write(text);
}
@Override
public void destroy() {}
};
FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(filter); registrationBean.addUrlPatterns(commonJsPattern); return registrationBean; } }
两种方式都可以,建议使用的是第一种,从根源解决
<a name="d6L8V"></a>
# 9. 获取 Druid 的监控数据
Druid 的监控数据可以在 开启 StatFilter 后,通过 DruidStatManagerFacade 进行获取;<br />DruidStatManagerFacade#getDataSourceStatDataList 该方法可以获取所有数据源的监控数据,除此之外 DruidStatManagerFacade 还提供了一些其他方法,可以按需选择使用。
```java
@RestController
@RequestMapping(value = "/druid")
public class DruidStatController {
@GetMapping("/stat")
public Object druidStat(){
// 获取数据源的监控数据
return DruidStatManagerFacade.getInstance().getDataSourceStatDataList();
}
}