Druid是阿里巴巴的一个数据库连接池开源框架,准确来说它不仅仅包括数据库连接池这么简单,Druid在监控、可扩展性、稳定性和性能方面都有明显的优势。Druid提供了Filter-Chain模式的扩展API,可以自己编写Filter拦截JDBC中的任何方法,可以在上面做任何事情,比如说性能监控、SQL审计、用户名密码加密、日志等等。
一、主流连接池对比
常用的主流开源数据库连接池有C3P0、DBCP、Tomcat Jdbc Pool、BoneCP、Druid等
C3p0: 开源的JDBC连接池,实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。单线程,性能较差,适用于小型系统,代码600KB左右。
DBCP (Database Connection Pool):由Apache开发的一个Java数据库连接池项目, Jakarta commons-pool对象池机制,Tomcat使用的连接池组件就是DBCP。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar,预先将数据库连接放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完再放回。单线程,并发量低,性能不好,适用于小型系统。
Tomcat Jdbc Pool:Tomcat在7.0以前都是使用common-dbcp做为连接池组件,但是dbcp是单线程,为保证线程安全会锁整个连接池,性能较差,dbcp有超过60个类,也相对复杂。Tomcat从7.0开始引入了新增连接池模块叫做Tomcat jdbc pool,基于Tomcat JULI,使用Tomcat日志框架,完全兼容dbcp,通过异步方式获取连接,支持高并发应用环境,超级简单核心文件只有8个,支持JMX,支持XA Connection。连接远程的数据库,而网络质量很差,经常断开连接。用dbcp,经常死锁,Druid在这种恶劣的工况下,也不行。最后用的tomcat7连接池,搞定。
BoneCP:官方说法BoneCP是一个高效、免费、开源的Java数据库连接池实现库。设计初衷就是为了提高数据库连接池性能,根据某些测试数据显示,BoneCP的速度是最快的,要比当时第二快速的连接池快25倍左右,完美集成到一些持久化产品如Hibernate和DataNucleus中。BoneCP特色:高度可扩展,快速;连接状态切换的回调机制;允许直接访问连接;自动化重置能力;JMX支持;懒加载能力;支持XML和属性文件配置方式;较好的Java代码组织,100%单元测试分支代码覆盖率;代码40KB左右。
Druid:Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能,是一个可用于大数据实时查询和分析的高容错、高性能的开源分布式系统,尤其是当发生代码部署、机器故障以及其他产品系统遇到宕机等情况时,Druid仍能够保持100%正常运行。主要特色:为分析监控设计;快速的交互式查询;高可用;可扩展;Druid是一个开源项目,源码托管在github上。
二、springboot整合druid
springboot整合有两种方式,第一种方式使用java配置,第二种方式使用注解配置,下面我们分别使用两种方式进行介绍。
准备工作:引入依赖包
mysql
mysql-connector-java
5.1.35
com.alibaba
druid-spring-boot-starter
1.1.0
org.projectlombok
lombok
1.16.20
log4j
log4j
1.2.16
compile
为了方便创建实体类,引入lombok
jar包,省缺set和get方法,不引用log4j
jar包会报错。
配置文件application.properties
# 数据库配置
spring.datasource.name=test
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
######################### Druid连接池的配置信息 #################
#初始化连接大小
spring.druid.initialSize=5
#最小连接池数量
spring.druid.minIdle=5
#最大连接池数量
spring.druid.maxActive=20
#获取连接时最大等待时间,单位毫秒
spring.druid.maxWait=60000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.druid.timeBetweenEvictionRunsMillis=60000
#配置一个连接在池中最小生存的时间,单位是毫秒
spring.druid.minEvictableIdleTimeMillis=300000
#测试连接
spring.druid.validationQuery=SELECT 1 FROM DUAL
#申请连接的时候检测,建议配置为true,不影响性能,并且保证安全性
spring.druid.testWhileIdle=true
#获取连接时执行检测,建议关闭,影响性能
spring.druid.testOnBorrow=false
#归还连接时执行检测,建议关闭,影响性能
spring.druid.testOnReturn=false
#是否开启PSCache,PSCache对支持游标的数据库性能提升巨大,oracle建议开启,mysql下建议关闭
spring.druid.poolPreparedStatements=false
#开启poolPreparedStatements后生效
spring.druid.maxPoolPreparedStatementPerConnectionSize=20
#配置扩展插件,常用的插件有=>stat:监控统计 log4j:日志 wall:防御sql注入
spring.druid.filters=stat,wall,log4j
#通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.druid.connectionProperties='druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000'
######################### Druid监控的配置信息 #################
druid.monitor.servletUrl=/druid/*
druid.monitor.allow=127.0.0.1
druid.monitor.deny=
druid.monitor.loginUsername=admin
druid.monitor.loginPassword=admin
druid.monitor.resetEnable=false
druid.monitor.logSlowSql=true
druid.monitor.filterUrl=/*
druid.monitor.exclustions='*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
druid.monitor.profileEnable=true
druid.monitor.principalCookieName=USER_COOKIE
druid.monitor.principalSessionName=USER_SESSION
方式一:使用java配置
1、读取数据库配置
package com.soft.springboot.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 数据库属性
* Created by USER on 2019/5/31.
*/
@Component
@ConfigurationProperties(prefix = "spring.datasource")
@Data
public class DataSourceProperties {
private String name;
private String url;
private String username;
private String password;
private String driverClassName;
}
2、读取druid连接池配置
package com.soft.springboot.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* druid数据源属性
* Created by USER on 2019/5/31.
*/
@Component
@ConfigurationProperties(prefix = "spring.druid")
@Data
public class DruidDataSourceProperties {
private int initialSize;
private int minIdle;
private int maxActive;
private int maxWait;
private int timeBetweenEvictionRunsMillis;
private int minEvictableIdleTimeMillis;
private String validationQuery;
private boolean testWhileIdle;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean poolPreparedStatements;
private int maxPoolPreparedStatementPerConnectionSize;
private String filters;
private String connectionProperties;
}
3、读取druid监控配置
package com.soft.springboot.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* druid监控服务属性
* Created by USER on 2019/5/31.
*/
@Component
@ConfigurationProperties(prefix = "druid.monitor")
@Data
public class DruidMonitorProperties {
// 监测服务配置
private String servletUrl;
private String allow;
private String deny;
private String loginUsername;
private String loginPassword;
private String resetEnable;
private String logSlowSql;
// 监测过滤配置
private String filterUrl;
private String exclustions;
private String profileEnable;
private String principalCookieName;
private String principalSessionName;
}
4、配置druid连接池
package com.soft.springboot.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* druid连接池配置
* Created by USER on 2019/5/31.
*/
@Configuration
public class DruidDataSourceConfigurater {
@Autowired
private DataSourceProperties dataSourceProperties;
@Autowired
private DruidDataSourceProperties druidDataSourceProperties;
@Bean(name="dataSource",destroyMethod = "close", initMethod="init")
@Primary
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setName(dataSourceProperties.getName());
dataSource.setUrl(dataSourceProperties.getUrl());
dataSource.setUsername(dataSourceProperties.getUsername());
dataSource.setPassword(dataSourceProperties.getPassword());
dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
dataSource.setInitialSize(druidDataSourceProperties.getInitialSize());
dataSource.setMinIdle(druidDataSourceProperties.getMinIdle());
dataSource.setMaxActive(druidDataSourceProperties.getMaxActive());
dataSource.setMaxWait(druidDataSourceProperties.getMaxWait());
dataSource.setTimeBetweenEvictionRunsMillis(druidDataSourceProperties.getTimeBetweenEvictionRunsMillis());
dataSource.setMinEvictableIdleTimeMillis(druidDataSourceProperties.getMinEvictableIdleTimeMillis());
dataSource.setValidationQuery(druidDataSourceProperties.getValidationQuery());
dataSource.setTestWhileIdle(druidDataSourceProperties.isTestWhileIdle());
dataSource.setTestOnBorrow(druidDataSourceProperties.isTestOnBorrow());
dataSource.setTestOnReturn(druidDataSourceProperties.isTestOnReturn());
dataSource.setPoolPreparedStatements(druidDataSourceProperties.isPoolPreparedStatements());
dataSource.setMaxPoolPreparedStatementPerConnectionSize(druidDataSourceProperties.getMaxPoolPreparedStatementPerConnectionSize());
try {
dataSource.setFilters(druidDataSourceProperties.getFilters());
} catch (SQLException e) {
e.printStackTrace();
}
dataSource.setConnectionProperties(druidDataSourceProperties.getConnectionProperties());
return dataSource;
}
}
5、配置druid监控服务
package com.soft.springboot.config;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* Druid监控配置
* Created by USER on 2019/5/31.
*/
@Configuration
public class DruidMonitorConfigurater {
@Autowired
private DruidMonitorProperties monitorProperties;
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean();
// 设置Servlet
registrationBean.setServlet(new StatViewServlet());
// 设置监控服务url
registrationBean.addUrlMappings(monitorProperties.getServletUrl());
// 设置访问白名单
registrationBean.addInitParameter("allow", monitorProperties.getAllow());
// 设置访问黑名单
registrationBean.addInitParameter("deny", monitorProperties.getDeny());
// 设置登录账号
registrationBean.addInitParameter("loginUsername", monitorProperties.getLoginUsername());
// 设置登录密码
registrationBean.addInitParameter("loginPassword", monitorProperties.getLoginPassword());
// 设置是否可以重置数据
registrationBean.addInitParameter("resetEnable", monitorProperties.getResetEnable());
// 配置打印慢的sql
registrationBean.addInitParameter("logSlowSql", monitorProperties.getLogSlowSql());
return registrationBean;
}
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
// 设置过滤器
registrationBean.setFilter(new WebStatFilter());
// 添加过滤规则
registrationBean.addUrlPatterns(monitorProperties.getFilterUrl());
// 设置忽略内容
registrationBean.addInitParameter("exclustions", monitorProperties.getExclustions());
// 监控单个url调用的sql列表
registrationBean.addInitParameter("profileEnable", monitorProperties.getProfileEnable());
registrationBean.addInitParameter("principalCookieName", monitorProperties.getPrincipalCookieName());
registrationBean.addInitParameter("principalSessionName", monitorProperties.getPrincipalSessionName());
return registrationBean;
}
}
方法二:使用注解配置
1、配置druid拦截器
package com.soft.springboot.config;
import com.alibaba.druid.support.http.WebStatFilter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
/**
* Druid的拦截器配置
* Created by USER on 2019/5/31.
*/
@WebFilter(filterName = "DruidFilter", urlPatterns = "/*", initParams = {
@WebInitParam(name = "exclusions", value = "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源
})
public class DruidFilter extends WebStatFilter {
}
2、配置druid监控服务
package com.soft.springboot.config;
import com.alibaba.druid.support.http.StatViewServlet;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
/**
* Druid监控服务配置
* Created by USER on 2019/5/31.
*/
@WebServlet(urlPatterns = "/druid/*",
initParams = {
@WebInitParam(name = "allow", value = "127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问)
@WebInitParam(name = "deny", value = "192.168.16.111"),// IP黑名单 (存在共同时,deny优先于allow)
@WebInitParam(name = "loginUsername", value = "admin"),// 用户名
@WebInitParam(name = "loginPassword", value = "admin"),// 密码
@WebInitParam(name = "resetEnable", value = "false")// 禁用HTML页面上的“Reset All”功能
})
public class DruidServlet extends StatViewServlet {
private static final long serialVersionUID = -6085007333934055609L;
}
3、对于基于注解的Filter和Servlet需要在SpringBoot的启动类上打上自动扫描注解
package com.soft.springboot;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@ServletComponentScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
启动springboot,访问http://localhost:8080/druid/