zoukankan      html  css  js  c++  java
  • 初识数据库连接池开源框架Druid

    Druid是阿里巴巴的一个数据库连接池开源框架,准确来说它不仅仅包括数据库连接池这么简单,它还提供强大的监控和扩展功能。本文仅仅是在不采用Spring框架对Druid的窥探,采用目前最新版本druid1.0.26 github地址:https://github.com/alibaba/druid

    在开始之前还是再说说为什么不配套使用Spring来使用Druid连接池,原因其实很简单,在Spring框架的配置文件中仅仅一个配置datasource就可以使用Druid了。那到底配置这个datasource数据源时Spring到底对它做了什么呢?它到底是怎么来实现这个datasource数据源的呢?如果不知其二只知其一,那才真是只是个搬砖的。

    下面我们正式开始吧,首先还是一览工程包结构。

    同样有两个jar需要引入,一是druid,二是mysql-connector。

    我们首先实现util包里的DBPoolConnection类,这个类用来创建数据库连接池单例以及返回一个数据库连接。为什么数据库连接池需要单例呢?原因其实很简单,我们可以想象在一个web应用中,同时可能会存在多个请求如果为每一个请求都创建一个数据库连接池,那还有什么意义呢?应该是不论有多少个并发请求,都应该只存在一个数据库连接池,在这个数据库连接池中为每个请求创建一个数据库连接

     1 package util;
     2 
     3 import java.io.File;
     4 import java.io.FileInputStream;
     5 import java.io.InputStream;
     6 import java.sql.SQLException;
     7 import java.util.Properties;
     8 
     9 import com.alibaba.druid.pool.DruidDataSource;
    10 import com.alibaba.druid.pool.DruidDataSourceFactory;
    11 import com.alibaba.druid.pool.DruidPooledConnection;
    12 
    13 /**
    14  * 要实现单例模式,保证全局只有一个数据库连接池
    15  * @author ylf
    16  *
    17  * 2016年10月21日
    18  */
    19 public class DBPoolConnection {
    20     private static DBPoolConnection dbPoolConnection = null;
    21     private static DruidDataSource druidDataSource = null;
    22     
    23     static {
    24         Properties properties = loadPropertiesFile("db_server.properties");
    25         try {
    26             druidDataSource = (DruidDataSource)DruidDataSourceFactory.createDataSource(properties);    //DruidDataSrouce工厂模式
    27         } catch (Exception e) {
    28             e.printStackTrace();
    29         }
    30     }
    31     
    32     /**
    33      * 数据库连接池单例
    34      * @return
    35      */
    36     public static synchronized DBPoolConnection getInstance(){
    37         if (null == dbPoolConnection){
    38             dbPoolConnection = new DBPoolConnection();
    39         }
    40         return dbPoolConnection;
    41     }
    42 
    43     /**
    44      * 返回druid数据库连接
    45      * @return
    46      * @throws SQLException
    47      */
    48     public DruidPooledConnection getConnection() throws SQLException{
    49         return druidDataSource.getConnection();
    50     }
    51     /**
    52      * @param string 配置文件名
    53      * @return Properties对象
    54      */
    55     private static Properties loadPropertiesFile(String fullFile) {
    56         String webRootPath = null;
    57         if (null == fullFile || fullFile.equals("")){
    58             throw new IllegalArgumentException("Properties file path can not be null" + fullFile);
    59         }
    60         webRootPath = DBPoolConnection.class.getClassLoader().getResource("").getPath();
    61         webRootPath = new File(webRootPath).getParent();
    62         InputStream inputStream = null;
    63         Properties p =null;
    64         try {
    65             inputStream = new FileInputStream(new File(webRootPath + File.separator + fullFile));
    66             p = new Properties();
    67             p.load(inputStream);
    68         } catch (Exception e) {
    69             e.printStackTrace();
    70         } finally {
    71             try {
    72                 if (null != inputStream){
    73                     inputStream.close();
    74                 }
    75             } catch (Exception e) {
    76                 e.printStackTrace();
    77             }
    78         }
    79         
    80         return p;
    81     }
    82     
    83 }

    第26行代码实例化一个DruidDataSource时,我们可以通过Druid框架为我们提供的DruidDataSourceFactory创建出一个DruidDataSource实例,工厂模式给我们提供了大大的便利。

    第36行getInstance方法为我们创建出一个数据库连接池实例,这里即用到了单例模式,在这个地方我们可以使用synchronized方法来对getInstance加锁(懒加载)实现线程安全,同时我们也可以使用勤加载来实现线程安全即去掉synchronized关键字,删掉37-39行代码,将第20行代码修改为private static DBPoolConnection dbPoolConnection = new DBPoolConnection()。这两种方式各有其优缺点,懒加载好处就是“用到才实例化”,缺点就是“synchronized关键字对方法加锁的粒度稍稍有点大,采用同步的方式实现线程安全会带来额外的开销”,而勤加载的好处就是“不使用同步的方式实现线程安全,省去了同步机制带来的额外开销”,缺点即是“未用到也会实例化”。至于怎么选择,根据实际情况。这里是之前对单例模式的两篇博文,《单例模式》《再说单例模式的线程安全问题》

    第55行代码loadPropertiesFile方法是对properties配置文件的加载。

    我们在这个类所做的工作差不多就是在spring配置文件中的那一句<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">。很简单的一句话,这就是为什么我不想使用Spring框架来配合使用Druid,因为这只会造成只知其一不知其二的结果。

    我们接在来实现dao包中的DruidDao类,开始对数据进行持久化操作。由于我们没有用到MyBatis等持久层框架,所以我们不得不使用JDBC来操作数据库,虽然麻烦一点,但这是所有所有框架的基础。

     1 /**
     2  * 
     3  */
     4 package dao;
     5 
     6 import java.sql.PreparedStatement;
     7 import java.sql.SQLException;
     8 
     9 import com.alibaba.druid.pool.DruidPooledConnection;
    10 
    11 import util.DBPoolConnection;
    12 
    13 /**
    14  * @author ylf
    15  *
    16  * 2016年10月21日
    17  */
    18 public class DruidDao {
    19     
    20     public void insert(String sql){
    21         DBPoolConnection dbp = DBPoolConnection.getInstance();    //获取数据连接池单例
    22         DruidPooledConnection conn = null;
    23         PreparedStatement ps = null;
    24         try {
    25             conn = dbp.getConnection();    //从数据库连接池中获取数据库连接
    26             ps = conn.prepareStatement(sql);
    27             ps.executeUpdate();
    28         } catch (SQLException e) {
    29             e.printStackTrace();
    30         } finally {
    31             try {
    32                 if (null != ps){
    33                     ps.close();
    34                 }
    35                 if (null != conn){
    36                     conn.close();
    37                 }
    38             } catch (Exception e) {
    39                 e.printStackTrace();
    40             }
    41         }
    42     }
    43 }

    我们只对数据做插入操作。下面我们测试一下,各个属性的含义可参考:https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8

     1 /**
     2  * 
     3  */
     4 package test;
     5 
     6 import dao.DruidDao;
     7 
     8 /**
     9  * @author ylf
    10  *
    11  * 2016年10月21日
    12  */
    13 public class Client {
    14 
    15     /**
    16      * @param args
    17      */
    18     public static void main(String[] args) {
    19         DruidDao druidDao = new DruidDao();
    20         String sql = "insert into test (name) values("keven")";
    21         druidDao.insert(sql);
    22     }
    23 
    24 }

    查看数据库插入成功。

    另外db_server.properties数据库的配置文件如下:

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/DruidTest
    username=root
    password=0000
    filters=stat
    initialSize=2
    maxActive=300
    maxWait=60000
    timeBetweenEvictionRunsMillis=60000
    minEvictableIdleTimeMillis=300000
    validationQuery=SELECT 1
    testWhileIdle=true
    testOnBorrow=false
    testOnReturn=false
    poolPreparedStatements=false
    maxPoolPreparedStatementPerConnectionSize=200
  • 相关阅读:
    java开发中的常见类和对象-建议阅读时间3分钟
    周末学习-泛型-就是传入什么类型就是什么类型-花了一个半小时
    实习第二天-String对象的不可变性-未解决
    实习第二天-java参数传递-精华在文章最后2句话
    实习第二天-对象-对象引用-引用变量-精-精-精-下雨天
    实习第一天:try和catch的使用
    实习第二天-今年第一场雨-方法的重载(马上想到println()函数和abs(函数))
    实习第一周第一天:接口 extends是继承类,implement是实现接口,原接口里面的方法填充,方法名也是不变,重写override是父类的方法名不变,把方法体给改了
    实习第一天:static 声明的 变量和 方法
    JavaWeb学习总结(二)-修改Tomcat服务器的端口(半年之后再总结)
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/5986395.html
Copyright © 2011-2022 走看看