Druid的简介
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。Druid是阿里巴巴开发的号称为监控而生的数据库连接池!
同时Druid不仅仅是一个数据库连接池,它包括四个部分:
Druid是一个JDBC组件,它包括三个部分:
基于Filter-Chain模式的插件体系。
DruidDataSource 高效可管理的数据库连接池。
SQLParser
Druid的功能
1、替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
2、可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
3、数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。
4、SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。
5、扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。
所以Druid可以:
1、充当数据库连接池。
2、可以监控数据库访问性能
3、获得SQL执行日志
配置 | 缺省值 | 说明 |
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。 在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。 5.5及以上版本有PSCache,建议开启。 |
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<com.alibaba.druid.filter.Filter>, 如果同时配置了filters和proxyFilters, 是组合关系,并非替换关系 |
Druid的简单使用
1、 首先在配置文件中导入好Druid连接池的依赖,还有MySQL的依赖
1 <dependency> 2 <groupId>mysql</groupId> 3 <artifactId>mysql-connector-java</artifactId> 4 <version>8.0.33</version> 5 </dependency> 6 7 <dependency> 8 <groupId>com.alibaba</groupId> 9 <artifactId>druid</artifactId> 10 <version>1.2.20</version> 11 </dependency>
2、编写Druid的配置文件 druid.properties
1 driverClassName=com.mysql.cj.jdbc.Driver 2 username=root 3 password=root 4 url=jdbc:mysql://localhost:3306/databasename 5 initialSize=5 6 maxActive=10
3、编写测试类进行CRUD操作
1 public class DruidFactory { 2 @Test 3 public void testDruidFactory() throws Exception { 4 Properties properties = new Properties(); 5 InputStream resourceAsStream = DruidFactory.class.getClassLoader().getResourceAsStream("druid.properties"); 6 properties.load(resourceAsStream); 7 8 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); 9 10 Connection connection = dataSource.getConnection(); 11 12 String sql = "SELECT * FROM users;"; 13 14 PreparedStatement preparedStatement = connection.prepareStatement(sql); 15 16 ResultSet resultSet = preparedStatement.executeQuery(); 17 18 ResultSetMetaData metaData = resultSet.getMetaData(); 19 20 int columnCount = metaData.getColumnCount(); 21 22 List<Map> list = new ArrayList<>(); 23 24 while (resultSet.next()){ 25 Map map = new HashMap(); 26 for (int i = 1; i <= columnCount; i++) { 27 map.put(metaData.getColumnLabel(i),resultSet.getObject(i)); 28 } 29 list.add(map); 30 } 31 32 Iterator<Map> iterator = list.iterator(); 33 34 while (iterator.hasNext()){ 35 System.out.println(iterator.next()); 36 } 37 38 resultSet.close(); 39 40 preparedStatement.close(); 41 42 connection.close(); 43 44 } 45 }
上述的JDBC操作我以前的文章有具体的讲解Java JDBC连接数据库的CURD操作(JDK1.8 + MySQL8.0.33 + mysql-connector-java-8.0.27-bin驱动) - 琮墨 - 博客园 (cnblogs.com)
以上就是最基本的Druid连接池的使用,但是在实际上,我们不会每次都进行加载配置文件再获取连接这种操作,所以我们可以封装一个工具类来帮助我们简化连接操作
DruidUtils的简单封装
1 public class DruidConnection { 2 private static DataSource dataSource = null; 3 4 static { 5 Properties properties = new Properties(); 6 InputStream resourceAsStream = DruidConnection.class.getClassLoader().getResourceAsStream("druid.properties"); 7 try { 8 properties.load(resourceAsStream); 9 dataSource = DruidDataSourceFactory.createDataSource(properties); 10 }catch (Exception e) { 11 throw new RuntimeException(e); 12 } 13 14 } 15 16 public static Connection getConnection() throws SQLException { 17 return dataSource.getConnection(); 18 } 19 20 public static void closeConnect(Connection connection) throws SQLException { 21 connection.close(); 22 } 23 }
用静态代码块来获取连接,调用静态方法可以直接获取到连接,这样就简化了每次都要进行加载配置文件等繁琐操作,直接调用静态方法即可获取连接。
Druid对于线程的封装
1 public class DruidThread { 2 private static DataSource dataSource = null; 3 private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); 4 5 static { 6 Properties properties = new Properties(); 7 InputStream resourceAsStream = DruidThread.class.getClassLoader().getResourceAsStream("druid.properties"); 8 try { 9 properties.load(resourceAsStream); 10 dataSource = DruidDataSourceFactory.createDataSource(properties); 11 } catch (Exception e) { 12 throw new RuntimeException(e); 13 } 14 15 } 16 17 public static Connection getConnection() throws SQLException { 18 Connection connection = threadLocal.get(); 19 if (connection == null){ 20 dataSource.getConnection(); 21 threadLocal.set(connection); 22 } 23 return connection; 24 } 25 26 public static void closeConnection() throws SQLException { 27 Connection connection = threadLocal.get(); 28 if (connection != null) { 29 threadLocal.remove(); 30 connection.setAutoCommit(true); 31 connection.close(); 32 } 33 } 34 }
将connection存放在线程本地量中,同一线程下的各业务逻辑层不需要用参数进行Connection传递,而且可以直接在线程本地量中获取当前i线程的连接,如果没有,那么创建一个新的连接。
标签:数据库,Druid,properties,connection,简单,连接,连接池 From: https://www.cnblogs.com/congmo/p/17766125.html