Druid简介

Druid是一个JDBC组件库,包括数据库连接池、SQL Parser等组件。

为什么要选Druid

主要功能对比

Druid

BoneCp

DBCP

C3p0

proxool

JBoss

Tomcat-Jdbc

LRU







?

PSCache








PSCache-Oracle-Optimized








ExceptionSorter








更新维护








LRU

LRU是一个关键性指标,特别是Oracle,每个Connection对应数据库端的一个进程,如果数据库连接池遵从LRU,有助于数据库服务器优化,这是重要的指标。在测试中,Druid、DBCP、Proxool是遵守LRP的。BoneCp、C3P0则不是.BoneCP在mock环境下性能可能好,但是在真实环境中则就不好了。

PSCache

PsCache是数据库连接池的关键指标。在Oracle中,类似于SELECT NAME FROM USER WHERE ID = ?这样的SQL,启用PSCache和不启用PSCache的性能可能是相差一个数量级的。Proxool是不支持PSCache的数据库连接池,如果使用Oracle、SQL Server、DB2、Sybase这样支持游标的数据库,那你就完全不用考虑Proxool。

PSCache-Oracle-Optimized

Oracle 10系列的Driver,如果开启PSCache,会占用大量的内存,必须做特别的处理,启用内部的EnterImplicitCache等方法优化才能够减少内存的占用。这个功能只有DruidDataSource有。如果你使用的是Oracle Jdbc,你应该毫不犹豫采用DruidDataSource。

ExceptionSorter

ExceptionSorter是一个很重要的容错特性,如果一个连接产生了一个不可回复的错误,必须立刻从连接池中去掉,否则会连续产生大量错误。这个特性目前只有JBoss和Druid实现。Druid的实现参考自JBoss,经过长期生产反馈补充。

配置Maven

Druid0.1.18之后版本都发布在maven中央仓库中,所以只需要在pom.xml中加上dependency就可以了。如下:

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.0.29</version>
</dependency>

DruidDataSource支持的数据库类型

理论上说,支持所有有jdbc驱动的数据库。实际测试过的有

数据库 支持状态
mysql   支持,大规模使用
oracle  支持,大规模使用
sqlserver   支持
postgres    支持
db2 支持
h2  支持
derby   支持
sqlite  支持
sybase  支持

配置DruidDataSource参考配置

以下是一个连接池配置实例

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
      <!-- 基本属性 url、user、password -->
      <property name="url" value="${jdbc_url}" />
      <property name="username" value="${jdbc_user}" />
      <property name="password" value="${jdbc_password}" />

       <!-- 初始化连接大小 -->
      <property name="initialSize" value="1" />
      <!-- 连接池最小空闲-->
      <property name="minIdle" value="1" /> 
      <!-- 连接池最大使用链接数量 -->
      <property name="maxActive" value="20" />

      <!-- 配置获取连接等待超时的时间 -->
      <property name="maxWait" value="60000" />

      <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
      <property name="timeBetweenEvictionRunsMillis" value="60000" />

      <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
      <property name="minEvictableIdleTimeMillis" value="300000" />

      <property name="validationQuery" value="SELECT 'x'" />
      <property name="testWhileIdle" value="true" />
      <property name="testOnBorrow" value="false" />
      <property name="testOnReturn" value="false" />

      <!-- 打开PSCache,并且指定每个连接上PSCache的大小 如果是mysql数据库此配置设为false-->
      <property name="poolPreparedStatements" value="true" />
      <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />

      <!-- 配置监控统计拦截的filters -->
      <property name="filters" value="stat" /> 
  </bean>

通常来说,只需要修改initialSize、minIdle、maxActive。

如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。分库分表较多的数据库,建议配置为false。

Druid根据URL配置自动识别DriverClass

Druid可不必如下显式配置DriverClass

<property name="driverClassName" value="${ds1.jdbc.driverClassName}" />

Druid可根据URL前缀自动识别DriverClass,下表列出常用的几种

前缀

DriverClass

描述信息

jdbc:mysql

com.mysql.jdbc.Driver

jdbc:oracle

oracle.jdbc.driver.OracleDriver

jdbc:microsoft

com.microsoft.jdbc.sqlserver.SQLServerDriver

数据库密码加密

数据库密码直接写在配置中,会存在一定的安全风险。Druid提供了一种对数据库密码加密的手段ConfigFilter。当然ConfigFilter除了提供数据库加密功能外,还提供了读取本地配置文件和读取远程http服务器的配置文件功能。此处对后两种不做具体的描述。

执行命令加密数据库密码

在命令行中执行如下命令

java -cp druid-1.0.16.jar com.alibaba.druid.filter.config.ConfigTools you_password

输出如下

privateKey:MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEA6+4avFnQKP+O7bu5YnxWoOZjv3no4aFV558HTPDoXs6EGD0HP7RzzhGPOKmpLQ1BbA5viSht+aDdaxXp6SvtMQIDAQABAkAeQt4fBo4SlCTrDUcMANLDtIlax/I87oqsONOg5M2JS0jNSbZuAXDv7/YEGEtMKuIESBZh7pvVG8FV531/fyOZAiEA+POkE+QwVbUfGyeugR6IGvnt4yeOwkC3bUoATScsN98CIQDynBXC8YngDNwZ62QPX+ONpqCel6g8NO9VKC+ETaS87wIhAKRouxZL38PqfqV/WlZ5ZGd0YS9gA360IK8zbOmHEkO/AiEAsES3iuvzQNYXFL3x9Tm2GzT1fkSx9wx+12BbJcVD7AECIQCD3Tv9S+AgRhQoNcuaSDNluVrL/B/wOmJRLqaOVJLQGg==

输入数据库密码,得到加密后的结果

配置数据源,配置Druid数据源对数据库密码进行解密

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
     init-method="init" destroy-method="close">
     <property name="url" value="jdbc:derby:memory:spring-test;create=true" />
     <property name="username" value="sa" />
     <property name="password" value="${password}" />
     <property name="filters" value="config" />
     <property name="connectionProperties" value="config.decrypt=true;config.decrypt.key=${publickey}" />
</bean>

除了在DruidDataSource的connectionProperties中执行config.decrypt=true还可以通过以下两种方式配置:

  • 在配置文件中指定config.decrypt=true
  • 在jvm启动参数中指定-Ddruid.config.decrypt=true

连接泄露检测

当程序存在缺陷时,申请的连接忘记关闭,这时候,就存在连接泄漏了。Druid提供了 RemoveAbandanded相关配置,用来关闭长时间不使用的连接。如下:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    ... ...
    <property name="removeAbandoned" value="true" /> <!-- 打开removeAbandoned功能 -->
    <property name="removeAbandonedTimeout" value="1800" /> <!-- 1800秒,也就是30分钟 -->
    <property name="logAbandoned" value="true" /> <!-- 关闭abanded连接时输出错误日志 -->
    ... ...
  </bean

配置removeAbandoned对性能会有一些影响,建议怀疑存在泄露之后再打开。在上面的配置中,如果连接超过30分钟未关闭,就会被强行回收,并且日志记连接申请时

内置监控页面闭查看连接堆栈信息

当removeAbandoned=true之后,可以在内置监控界面datasource.html中查看ActiveConnetion StatckTrace属性的,可以看到未关闭连接的具体堆栈信息,从而方便查出哪些连接在的配置会在下文中描述。

web应用

如果配置了WebStatFilter,可以在内置监控页面weburi-detail.html中,查看JdbcPoolConnectionOpenCount和JdbcPoolConnectionCloseCount属性,如果不相等,就是泄露了。

Druid的监控统计功能

Druid的监控统计功能时通过filter-chain扩展实现。如果要打开监控统计功能要配置StatFilter.StatFilter是Druid是内置的,用于统计监控信息。

别名配置

StatFilter的别名是stat,这个别名映射配置信息保存在druid-xxx.jar!/META_INF/druid-filter.properties.
在Spring中使用别名配置方式如下:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="filters" value="stat" />
  </bean>

组合配置

StatFilter可以和其他的Filter配置使用,比如:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="filters" value="stat,log4j" />
  </bean>

在上面的配置中,StatFilter和Log4jFilter组合使用。

通过proxyFilters属性配置

别名配置是通过filters属性配置的,filters属性的类型是String。如果要通过bean的方式配置,使用proxyFilters属性。

<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
    <property name="slowSqlMillis" value="10000" />
    <property name="logSlowSql" value="true" />
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    init-method="init" destroy-method="close">
    ... ...
    <property name="filters" value="log4j" />
    <property name="proxyFilters">
        <list>
            <ref bean="stat-filter" />
        </list>
    </property>
</bean>

其中filters和proxyFilters属性是组合关系,不是替换的,在上面的配置中,dataSource有了两个Filter,statFilter和Log4jFilter。

SQL合并配置

当你程序中国存在没有参数化的sql执行时,sql统计的效果会不好。比如:

select * from t where id = 1
select * from t where id = 2
select * from t where id = 3

在统计中,显示为3条sql,这不是我们期望的效果。StatFilter提供合并的功能,能将这3个SQL合并为如下的SQL

select * from t where id = ?

配置StatFilter的mergeSql属性

<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
    <property name="mergeSql" value="true" />
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
    init-method="init" destroy-method="close">
    ... ...
    <property name="proxyFilters">
        <list>
            <ref bean="stat-filter" />
        </list>
    </property>
</bean>

StatFilter支持一种简化配置方式,和上面的配置等同

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="filters" value="mergeStat" />
  </bean>

mergeStat是MergeStatFilter缩写,MergeStatFilter的实现如下:

public class MergeStatFilter extends StatFilter {
    public MergeStatFilter() {
        super.setMergeSql(true);
    }
  }

从实现代码来看,仅仅是一个mergeSql的缺省值
也可以通过connectProperties属性来打开mergeSql功能

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="filters" value="stat" />
    <property name="connectionProperties" value="druid.stat.mergeSql=true" />
  </bean>

或者通过增加jvm的参数配置
-Ddruid.stat.mergeSql=true

慢SQL记录

StatFilter属性slowSqlMillis用来配置SQL慢的标准,执行时间超过slowSqlMills的就是慢。slowSqlMills的缺省配置值为3000,也就是3s.

<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
    <property name="slowSqlMillis" value="10000" />
    <property name="logSlowSql" value="true" />
</bean>

以上配置将slowSqlMills修改为10s,并且通过日志输出执行慢的SQL。
slowSqlMills属性也可以通过connectProperties来配置。例如

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="filters" value="stat" />
    <property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" />
  </bean>

合并多个DruidDataSource的监控数据

缺省多个DruidDataSource的监控数据是各自独立的,在druid-0.2.17版本之后,支持配置共用监控数据,配置参数为useGloalDataSourceStat。如下

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="useGlobalDataSourceStat" value="true" />
  </bean>

或通过jvm启动参数来指定

-Ddruid.useGlobalDataSourceStat=true

全部使用jvm启动参数来配置,就可以这样

-Ddruid.filters=mergeStat -Ddruid.useGlobalDataSourceStat=true

使用Druid的内置监控页面

内置监控页面是一个Servlet,Druid内置提供了一个StatViewServlet用户展示Druid的统计信息。
这个StatViewServlet的用途包括:

  • 提供监控信息展示的html页面
  • 提供监控信息的JSON API

配置web.xml

StatViewServlet是一个标准的javax.servlet.http.HttpServlet,需要配置在你web应用中的WEB-INF/web.xml

<servlet>
      <servlet-name>DruidStatView</servlet-name>
      <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>DruidStatView</servlet-name>
      <url-pattern>/druid/*</url-pattern>
  </servlet-mapping>

根据配置中的url-pattern来访问内置监控页面,如上配置,内置监控页面的首页是/druid/index.html

配置监控页面访问密码

需要配置Servlet的loginUsername和loginPassword这两个初始参数。

<!-- 配置 Druid 监控信息显示页面 -->  
<servlet>  
    <servlet-name>DruidStatView</servlet-name>  
    <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  
    <init-param>  
    <!-- 允许清空统计数据 -->  
    <param-name>resetEnable</param-name>  
    <param-value>true</param-value>  
    </init-param>  
    <init-param>  
    <!-- 用户名 -->  
    <param-name>loginUsername</param-name>  
    <param-value>druid</param-value>  
    </init-param>  
    <init-param>  
    <!-- 密码 -->  
    <param-name>loginPassword</param-name>  
    <param-value>druid</param-value>  
    </init-param>  
</servlet>  
<servlet-mapping>  
    <servlet-name>DruidStatView</servlet-name>  
    <url-pattern>/druid/*</url-pattern>  
</servlet-mapping>
配置allow和deny

StatViewServlet展示出来的监控信息比较敏感,是系统运行的内部情况,如果你需要做访问控制,可以配置allow和deny这个来那个参数

<servlet>
      <servlet-name>DruidStatView</servlet-name>
      <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
    <init-param>
        <param-name>allow</param-name>
        <param-value>128.242.127.1/24,128.242.128.1</param-value>
    </init-param>
    <init-param>
        <param-name>deny</param-name>
        <param-value>128.242.127.4</param-value>
    </init-param>
  </servlet>
  • 判断规则
  • deny优先于allow,如果在deny列表中,就算又在allow列表中,也会被拒绝
  • 如果allow没有配置或者为空,则允许所有访问
  • ip配置规则
  • 配置格式
<IP>
  或者
  <IP>/<SUB_NET_MASK_size>

其中

128.242.127.1/24

24表示,前24位是子网掩码,对比的时候,前面24位相同就是匹配

  • 不支持IPV6
  • 由于匹配规则不支持IPV6,配置了allow和deny之后,会导致IPV6无法访问。
配置resetEnable

在StatViewSerlvet输出的html页面中,有一个功能是Reset ALL,执行这个操作之后,会导致所有计数器清零,重新计算。你可以通过配置参数关闭它。

<servlet>
      <servlet-name>DruidStatView</servlet-name>
      <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
    <init-param>
        <param-name>resetEnable</param-name>
        <param-value>false</param-value>
    </init-param>
  </servlet>

内置监控中配置Web关联监控

WebStatFilter用于采集web-jdbc关联监控数据

web.xml配置如下

<filter>
    <filter-name>DruidWebStatFilter</filter-name>
    <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
    <init-param>
        <param-name>exclusions</param-name>
        <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>DruidWebStatFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

exclusions配置

经常需要排除一些不必要的url,配置在init-param中。如下

<init-param>
        <param-name>exclusions</param-name>
        <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
    </init-param>

sessionStatMaxCount配置

缺省sessionStatMaxCount是1000个。可以按需配置。如下

<init-param>
        <param-name>sessionStatMaxCount</param-name>
        <param-value>1000</param-value>
    </init-param>

sessionStatEnalbe配置

可以关闭session统计功能

<init-param>
        <param-name>sessionStatEnable</param-name>
        <param-value>false</param-value>
    </init-param>

principalSessionName配置

可以配置principalSessionName,是的druid能够知道当前的session用户是谁。

<init-param>
        <param-name>principalSessionName</param-name>
        <param-value>xxx.user</param-value>
    </init-param>

根据需要,把其中的xxx.user修改为user信息中保存在session中的sessionName

principalCookieName

如果user信息保存在cookie中,可以通过配置principalCookieName,使得druid知道当前的user是谁

<init-param>
        <param-name>principalCookieName</param-name>
        <param-value>xxx.user</param-value>
    </init-param>

根据需要,把其中的xxx.user修改为你user信息保存在cookie中的cookieName。

profileEnalble

druid0.2.7版本开始支持profile,配置profileEnable能够监控单个url调用的sql列表。

<init-param>
    <param-name>profileEnable</param-name>
    <param-value>true</param-value>
</init-param>

配置SQL注入攻击

Druid提供了WallFilter,它是基于SQL语义分析来实现防御SQL注入攻击。配置方式如下

使用缺省配置的WallFilter

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      ...
      <property name="filters" value="wall"/>
  </bean>

结合其他Filter一起使用

WallFilter可以结合其他Filter一起使用

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      ...
      <property name="filters" value="wall,stat"/>
  </bean>

这样拦截检测的时间不在StatFilter统计的SQL执行时间内,
如果希望StatFilter统计的SQL执行时间包含拦截检测的时间,则使用如下配置

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      ...
      <property name="filters" value="stat,wall"/>
  </bean>

指定dbType

有时候,一些应用框架做了自己的JDBC Proxy Driver,使得DruidDataSourece无法正确识别数据库的类型,则需要特别指定,如下

<bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
      <property name="dbType" value="mysql" />
  </bean>

  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      ...
      <property name="proxyFilters">
          <list>
              <ref bean="wall-filter"/>
          </list>
      </property>
  </bean>

指定配置装载的目录

缺省情况下,配置装载的目录如下:

数据库类型

目录

mysql

META-INF/druid/wall/mysql

oracle

META-INF/druid/wall/oracle

sqlserver

META-INF/druid/wall/sqlserver

postgres

META-INF/druid/wall/postgres

从配置文件目录中以下文件中读取配置

deny-variant.txt
  deny-schema.txt
  deny-function.txt
  deny-table.txt
  deny-object.txt

配置装载的目录可以指定,如下

<bean id="wall-filter-config" class="com.alibaba.druid.wall.WallConfig" init-method="init">
      <!-- 指定配置装载的目录  -->
      <property name="dir" value="META-INF/druid/wall/mysql" />
  </bean>

  <bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
      <property name="dbType" value="mysql" />
      <property name="config" ref="wall-filter-config" />
  </bean>

  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
      ...
      <property name="proxyFilters">
          <list>
              <ref bean="wall-filter"/>
          </list>
      </property>
  </bean>

WallConfig详细说明

本身的配置

配置项

缺省值

dir

按照dbType分别配置: mysql : META-INF/druid/wall/mysql oracle : META-INF/druid/wall/oracle sqlserver : META-INF/druid/wall/sqlserver

WallFilter配置说明
配置项 缺省值 描述
logViolation    false   对被认为是攻击的SQL进行LOG.error输出
throwException  true    对被认为是攻击的SQL抛出SQLExcepton
config      
provider

刚开始引入WallFilter的时候,把logViolation设置为true,而throwException设置为false。就可以观察是否存在违规的情况,同时不影响业务运行。

日志记录JDBC执行的SQL

Druid提供了LogjFilter、Log4j2Filter、CommonsLogFilter和Slf4jFilter,用于输出JDBC执行的日志。这些Filter都是Filter-Chain扩展机制中的Filter

别名配置

在druid-xxx.jar!/META-INF/druid-filter.properties文件中描述了这四种Filter的别名

druid.filters.log4j=com.alibaba.druid.filter.logging.Log4jFilter
  druid.filters.log4j2=com.alibaba.druid.filter.logging.Log4j2Filter
  druid.filters.slf4j=com.alibaba.druid.filter.logging.Slf4jLogFilter
  druid.filters.commonlogging=com.alibaba.druid.filter.logging.CommonsLogFilter
  druid.filters.commonLogging=com.alibaba.druid.filter.logging.CommonsLogFilter

别名分别是log4j、log4j2、slf4j、commonlogging和commonLoggin只是大小写不同。

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
      init-method="init" destroy-method="close">
      ... ...
      <property name="filters" value="stat,log4j2" />
  </bean>

loggerName配置

LogFilter都是缺省使用四种不同的Logger执行输出,看实现代码:

public abstract class LogFilter {
      protected String          dataSourceLoggerName                 = "druid.sql.DataSource";
      protected String          connectionLoggerName                 = "druid.sql.Connection";
      protected String          statementLoggerName                  = "druid.sql.Statement";
      protected String          resultSetLoggerName                  = "druid.sql.ResultSet";
  }

可以根据你的需要修改,在log4j.properties文件上做配置时,注意配置使用相关的logger。

配置输出日志

缺省输入的日志信息全面,但是内容比较多,有时候我们需要定制化配置日志输出。

<bean id="log-filter" class="com.alibaba.druid.filter.logging.Log4jFilter">
    <property name="resultSetLogEnabled" value="false" />
</bean>

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ...
    <property name="proxyFilters">
        <list>
            <ref bean="log-filter"/>
        </list>
    </property>
</bean>

配置列表

参数  说明
dataSourceLogEnabled    所有DataSource相关的日志
connectionLogEnabled    所有连接相关的日志
connectionLogErrorEnabled   所有连接上发生异常的日志
statementLogEnabled 所有Statement相关的日志
statementLogErrorEnabled    所有Statement发生异常的日志
resultSetLogEnabled 
resultSetLogErrorEnabled    
connectionConnectBeforeLogEnabled   
connectionConnectAfterLogEnabled    
connectionCommitAfterLogEnabled 
connectionRollbackAfterLogEnabled   
connectionCloseAfterLogEnabled  
statementCreateAfterLogEnabled  
statementPrepareAfterLogEnabled 
statementPrepareCallAfterLogEnabled 
statementExecuteAfterLogEnabled 
statementExecuteQueryAfterLogEnabled    
statementExecuteUpdateAfterLogEnabled   
statementExecuteBatchAfterLogEnabled    
statementCloseAfterLogEnabled   
statementParameterSetLogEnabled 
resultSetNextAfterLogEnabled    
resultSetOpenAfterLogEnabled    
resultSetCloseAfterLogEnabled

log4j.properties配置

如果你使用log4j,可以通过log4j.properties文件配置日志输出选项,例如

log4j.logger.druid.sql=warn,stdout
  log4j.logger.druid.sql.DataSource=warn,stdout
  log4j.logger.druid.sql.Connection=warn,stdout
  log4j.logger.druid.sql.Statement=warn,stdout
  log4j.logger.druid.sql.ResultSet=warn,stdout

输出可执行的SQL

logFilter参数直接配置

<bean id="log-filter" class="com.alibaba.druid.filter.logging.Log4jFilter">
        <property name="statementExecutableSqlLogEnable" value="true" />
  </bean>

Druid监控记录的保存

Druid中有DruidDataSourece、Spring、Web等监控记录,其中DruidDataSourece提供了保存监控记录的API。

保存DruidDataSource的监控记录

DruidDataSource有一个属性timeBetweenLogStatsMillis,配置timeBetweenLogStatsMillis>0之后,DruidDataSource会定期把监控数据输出到日志中。

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="timeBetweenLogStatsMillis" value="300000" />
    ... ...
  </bean>

或者通过jvm启动参数来指定

-Ddruid.timeBetweenLogStatsMillis=300000

定制StatLogger

DruidDataSource是通过com.alibaba.druid.pool.DruidDataSourceStatLoggerImpl.DruidDataSourceStatLoggerImpl来实现输入监控数据到日志的,你可以自定义一个StatLogger,例如:

import com.alibaba.druid.pool.DruidDataSourceStatLoggerAdapter;
  import com.alibaba.druid.pool.DruidDataSourceStatLogger ;
  public class MyStatLogger extends DruidDataSourceStatLoggerAdapter implements DruidDataSourceStatLogger {
    ... ...
  }

配置如下

<bean id="myStatLogger" class="com.mycompany.MyStatLogger">
    ... ...
  </bean>
  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    ... ...
    <property name="statLogger" ref="myStatLogger" />
    ... ...
  </bean>