[数据库druid连接池实现]--Java版本

前言

     之前有介绍一篇关于自定义的数据库链接池实现,但是质量并不高。而且遭到博友的一脸嫌弃!确实,拿出来的东西就应该保证是正确的,或者质量高,否则很容易就误导了他人,显得TMD也不道德,所以今天专门重写之前的想法,当然,还有许多文章需要更新,后期我都会一一完善,希望对各位有一定的帮助。

     目前针对Java web应用使用的数据库链接池比较多也很杂,但稳定且好用的还是推荐阿里巴巴的druid(德鲁伊连接池)。那么下面就重点介绍自定义链接池和使用阿里巴巴的durid连接池,不足指出请指正。


什么是连接池?

       连接池是一种创建和维护JDBC连接对象集合的机制。维护连接对象池的主要目的是利用可重用性。只有在没有可用的连接对象时才会创建新的连接对象。这种技术可以提高应用程序的整体性能。本文将尝试展示如何将这种池化机制应用于Java应用程序。


为什么要用连接池?

       建立数据库连接是一个非常耗费资源的过程,需要大量的开销。而且,在多线程环境下,打开和关闭连接会使情况变得更糟。要了解创建新数据库连接的每个请求可能发生的情况,请考虑以下几点。数据库连接使用的是成立的DriverManager的数据源对象。

  • 应用程序可以调用getConnection()方法。
  • JDBC驱动程序请求一个JVM套接字。
  • JVM必须确保调用不会违反安全方面(小程序可能会出现这种情况)。
  • 在进入网络云之前,调用可能需要通过防火墙渗透。
  • 到达主机时,服务器处理连接请求。
  • 数据库服务器初始化连接对象并返回到JDBC客户端(再次通过相同的过程)。
  • 最后,我们得到一个连接对象。

       这只是幕后实际情况的简单概述。放心吧,实际的过程比这个更加复杂和精细。在单线程控制的环境中,数据库事务大部分是线性的,比如打开连接,完成数据库事务,关闭连接。实际应用更复杂; 连接池的机制可以增加性能,尽管还有许多对于应用程序整体性能至关重要的其他属性。

      连接池概念的复杂性在我们深入研究的过程中变得越来越难理解。但是,要感谢那些专门为连接池合作而制作图书馆的人们。这些库遵循JDBC的规范,并提供更简单的API来实际在Java应用程序中实现它们。

怎样使用连接池?

1、自定义链接池

连接池的管理用了享元模式,这里对连接池进行简单设计。

【一】、设计思路

     (1).连接池配置属性DBbean:里面存放可以配置的一些属性

     (2).连接池接口IConnectionPool:里面定义一些基本的获取连接的一些方法

     (3).接口实现ConnectionPool:对上面操作进行实现,并加入一些其他方法

     (4).连接池管理ConnectionPoolManager:管理所有的不同的连接池,所有的连接都能通过这里进行获得连接

     (5).另外还有几个测试类,和连接信息模拟的类,这里就不进行xml 和配置文件信息的读取了

【二】、测试代码实现(数据库驱动版本是5.1.38、连接池版本是阿里巴巴druid-1.1.5)

代码目录结构:


(1)配置文件类

packagecom.yjf.java.bean;

importjava.io.Serializable;

/**

 * Created by rooton 20170924.

 * Update date:

 * <p>

 * Time: 1:50 PM

 * Project:test-java

 * Package:com.yjf.java.bean

 * Describe :

 * <p>

 * Result of Test:test ok,test error

 * Command:

 * <p>

 * <p>

 * Email:  jifei.yang@ngaa.com.cn

 * StatusUsing online

 * Attention

 */

publicclassDBInfoimplementsSerializable{

    /* Connectionproperties */

    privateStringdriverName;

    privateStringurl;

    privateStringuserName;

    privateStringpassword;

    privateStringpoolName;

    privateIntegerinitConnections;

    privateIntegermaxActiveConnections;

    privatelongconnectionTimeOut ;

    privatebooleanisCurrentConnection;

    privatebooleanisCheckPool;

    privatelonglazyCheck;

    privatelongperiodCheck ;

    privatelongreleaseConnTime;

    privatelongdestroyConnTime;

 

    publicDBInfo(){

    }

 

    publicDBInfo(StringdriverName,Stringurl,StringuserName,Stringpassword,StringpoolName,IntegerinitConnections,IntegermaxActiveConnections,longconnectionTimeOut,booleanisCurrentConnection,booleanisCheckPool,longlazyCheck,longperiodCheck,longreleaseConnTime,longdestroyConnTime){

        this.driverName=driverName;

        this.url=url;

        this.userName=userName;

        this.password=password;

        this.poolName=poolName;

        this.initConnections=initConnections;

        this.maxActiveConnections=maxActiveConnections;

        this.connectionTimeOut=connectionTimeOut;

        this.isCurrentConnection=isCurrentConnection;

        this.isCheckPool=isCheckPool;

        this.lazyCheck=lazyCheck;

        this.periodCheck=periodCheck;

        this.releaseConnTime=releaseConnTime;

        this.destroyConnTime=destroyConnTime;

    }

 

    publicStringgetDriverName(){

        returndriverName;

    }

 

    publicvoidsetDriverName(StringdriverName){

        this.driverName=driverName;

    }

 

    publicStringgetUrl(){

        returnurl;

    }

 

    publicvoidsetUrl(Stringurl){

        this.url=url;

    }

 

    publicStringgetUserName(){

        returnuserName;

    }

 

    publicvoidsetUserName(StringuserName){

        this.userName=userName;

    }

 

    publicStringgetPassword(){

        returnpassword;

    }

 

    publicvoidsetPassword(Stringpassword){

        this.password=password;

    }

 

    publicStringgetPoolName(){

        returnpoolName;

    }

 

    publicvoidsetPoolName(StringpoolName){

        this.poolName=poolName;

    }

 

    publicIntegergetInitConnections(){

        returninitConnections;

    }

 

    publicvoidsetInitConnections(IntegerinitConnections){

        this.initConnections=initConnections;

    }

 

    publicIntegergetMaxActiveConnections(){

        returnmaxActiveConnections;

    }

 

    publicvoidsetMaxActiveConnections(IntegermaxActiveConnections){

        this.maxActiveConnections=maxActiveConnections;

    }

 

    publiclonggetConnectionTimeOut(){

        returnconnectionTimeOut;

    }

 

    publicvoidsetConnectionTimeOut(longconnectionTimeOut){

        this.connectionTimeOut=connectionTimeOut;

    }

 

    publicbooleanisCurrentConnection(){

        returnisCurrentConnection;

    }

 

    publicvoidsetCurrentConnection(booleancurrentConnection){

        isCurrentConnection=currentConnection;

    }

 

    publicbooleanisCheckPool(){

        returnisCheckPool;

    }

 

    publicvoidsetCheckPool(booleancheckPool){

        isCheckPool=checkPool;

    }

 

    publiclonggetLazyCheck(){

        returnlazyCheck;

    }

 

    publicvoidsetLazyCheck(longlazyCheck){

        this.lazyCheck=lazyCheck;

    }

 

    publiclonggetPeriodCheck(){

        returnperiodCheck;

    }

 

    publicvoidsetPeriodCheck(longperiodCheck){

        this.periodCheck=periodCheck;

    }

 

    publiclonggetReleaseConnTime(){

        returnreleaseConnTime;

    }

 

    publicvoidsetReleaseConnTime(longreleaseConnTime){

        this.releaseConnTime=releaseConnTime;

    }

 

    publiclonggetDestroyConnTime(){

        returndestroyConnTime;

    }

 

    publicvoidsetDestroyConnTime(longdestroyConnTime){

        this.destroyConnTime=destroyConnTime;

    }

}

 

(2)连接池的接口类

packagecom.yjf.java.core;

 

importjava.sql.Connection;

 

/**

 * Created by rooton 20170924.

 * Update date:

 * <p>

 * Time: 2:39 PM

 * Project:test-java

 * Package:com.yjf.java.core

 * Describe :

 * <p>

 * Result of Test:test ok,test error

 * Command:

 * <p>

 * <p>

 * Email:  jifei.yang@ngaa.com.cn

 * StatusUsing online

 * Attention

 */

publicinterfaceIConnectionPool{

    // 1\获得连接

     ConnectiongetConnection();

 

    // 2\获得当前连接

     ConnectiongetCurrentConnecton();

 

    // 3\回收连接

     voidreleaseConn(Connectionconn);

 

    // 4\连接池是活动状态

     booleanisActive(BooleanisActiveNot);

 

    // 5\定时器,检查连接池

     voidcheackPool();

 

    // 6\定时检查关闭未占用的链接。

     voiddestroyFreeAndMoveToOther();

 

    // 7\销毁那些长时间不用的链接。

    voiddestroyLongTimeNotUseConn();

}

 

(3)连接池的实现类

packagecom.yjf.java.core;

 

importcom.yjf.java.bean.DBInfo;

 

importjava.sql.Connection;

importjava.sql.DriverManager;

importjava.sql.SQLException;

importjava.util.Timer;

importjava.util.TimerTask;

importjava.util.Vector;

 

/**

 * Created by rooton 20170924.

 * Update date:

 * <p>

 * Time: 2:39 PM

 * Project:test-java

 * Package:com.yjf.java.core

 * Describe :

 * <p>

 * Result of Test:test ok,test error

 * Command:

 * <p>

 * <p>

 * Email:  jifei.yang@ngaa.com.cn

 * StatusUsing online

 * Attention

 */

publicclassIConnectionPoolImplimplementsIConnectionPool{

    privatestaticThreadLocal<Connection>threadLocal=newThreadLocal<>();                          //将线程和连接绑定,保证事务能统一执行

    privateDBInfodbBean;                                                                             //连接池配置属性

    privateBooleanisActive=false;                                                                  //连接池活动状态

    privateIntegertotalConn=0;                                                                     //记录创建的总的连接数

    privateVector<Connection>freeConnection=newVector<>();                                        //空闲连接

    privateVector<Connection>activeConnection=newVector<>();                                      //活动连接

    privateVector<Connection>otherConnection=newVector<>();                                        // 其他连接

 

    publicIConnectionPoolImpl(DBInfodbBean){

        super();

        this.dbBean=dbBean;

        init();

        cheackPool();

        destroyFreeAndMoveToOther();

        destroyLongTimeNotUseConn();

    }

 

    //连接池状态

    publicbooleanisActive(BooleanisActiveNot){

        isActive=isActiveNot;

        returnisActive;

    }

 

    //初始化

    privatevoidinit(){

        try{

            IntegerminConn=dbBean.getInitConnections();

            //初始化最小连接数

            System.out.println("Info:初始化最小连接数-->"+minConn);

            for(inti=0;i<minConn;i++){

                Connectionconn;

                conn=newConnection();

                if(conn!=null){

                   freeConnection.add(conn);

                   totalConn=totalConn+1;

                }

            }

            //设置连接数据库池是活动的。

            isActive=true;

        }catch(Exceptione){

            e.printStackTrace();

        }

    }

 

    //获得当前连接

    publicConnectiongetCurrentConnecton(){

        //默认线程里面取

        Connectionconn=threadLocal.get();

        if(!isValid(conn)){

            conn=getConnection();

        }

        returnconn;

    }

 

    //获得连接

    publicsynchronizedConnectiongetConnection(){

        Connectionconn=null;

        try{

            //判断是否超过最大连接数限制

            if(totalConn<this.dbBean.getMaxActiveConnections()){

                IntegerfreeSize=freeConnection.size();

                IntegerotherSize=otherConnection.size();

                if(freeSize>0||otherSize>0){

 

                   intindex=0;

                   //判断是从空闲链接中获取链接,还是从其他链接中获取conn

                   if(freeSize>0){

                       conn=freeConnection.get(index);

 

                       if(conn!=null){

                            threadLocal.set(conn);

                       }

                       //移除一个链接,则需要添加一个链接到Vector中。

                       activeConnection.add(conn);

                       freeConnection.remove(index);

                   }else{

                       conn=otherConnection.get(index);

                       if(conn!=null){

                            threadLocal.set(conn);

                       }

                        //移除一个链接,则需要添加一个链接到Vector中。

                       activeConnection.add(conn);

                       otherConnection.remove(index);

                   }

 

                }else{

                   conn=newConnection();

                   activeConnection.add(conn);

                   totalConn++;

                }

                System.out.println("Info:空闲链接的数量-->"+freeConnection.size());

                System.out.println("Info:其他链接的数量-->"+otherConnection.size());

            }else{

                //继续获得连接,直到从新获得连接

                System.out.println("Info:等待获取新的链接。");

                wait(this.dbBean.getConnectionTimeOut());

                conn=getConnection();

            }

        }catch(Exceptione){

            e.printStackTrace();

        }

        returnconn;

    }

 

    //获得新连接

    privatesynchronizedConnectionnewConnection()

            throwsClassNotFoundException,SQLException{

        Connectionconn=null;

        if(dbBean!=null){

            Class.forName(dbBean.getDriverName());

            conn=DriverManager.getConnection(dbBean.getUrl(),

                   dbBean.getUserName(),dbBean.getPassword());

            System.out.println("Info:获取新的连接.");

        }

        returnconn;

    }

 

    //释放连接

    publicsynchronizedvoidreleaseConn(Connectionconn){

        System.out.println("Info:当前链接是-->"+conn);

        System.out.println("Info:活动的链接数量是-->"+activeConnection.size());

        //如果链接没有关闭

        if(isValid(conn)){

            freeConnection.add(conn);

            activeConnection.remove(conn);

            threadLocal.remove();

 

        }else{

            System.out.println("Info:无法释放该链接。");

        }

        notifyAll();   //需要唤醒等待。

    }

 

    //判断连接是否可用

    privatebooleanisValid(Connectionconn){

        try{

            if(conn==null||conn.isClosed()){

                returnfalse;

            }

        }catch(SQLExceptione){

            e.printStackTrace();

        }

        returntrue;

    }

 

    //定时检查关闭未占用的链接。

    publicsynchronizedvoiddestroyFreeAndMoveToOther(){

        newTimer().schedule(newTimerTask(){

            @Override

            publicvoidrun(){

                System.out.println("Info:----------------定时任务开始释放空闲连接,即移动到其他链接中----------------------");

                for(inti=0;i<freeConnection.size();i++){

                   ConnectionfreeConn=freeConnection.get(i);

                   if(isValid(freeConn)){

                        otherConnection.add(freeConn);

                       freeConnection.remove(freeConn);

                       threadLocal.remove();

                   }

                }

            }

        },dbBean.getReleaseConnTime(),dbBean.getReleaseConnTime());

 

    }

    //定时检查连接池情况

    @Override

    publicvoidcheackPool(){

        if(dbBean.isCheckPool()){

            newTimer().schedule(newTimerTask(){

                @Override

                publicvoidrun(){

                    IntegerfreeSize=freeConnection.size();

                   // 1.对线程里面的连接状态

                   if(activeConnection.size()==0&&freeSize>0){

                       System.out.println("Info:==========================定时任务开始关闭空闲连接=======================================");

                       try{

                            for(ConnectionfreeConn:freeConnection){

                                threadLocal.remove();

                                freeConn.close();       //需要先从当前线程中移除conn后,再关闭链接。

                            }

                            freeConnection.clear();

                       }catch(Exceptione){

                            e.printStackTrace();

                        }

                   }

                   totalConn=freeConnection.size()+activeConnection.size()+otherConnection.size();

                   // 2.连接池最小最大连接数

                   System.out.println("Info:free连接数-->"+freeConnection.size());

                   System.out.println("Info:active连接数-->"+activeConnection.size());

                   System.out.println("Info:other连接数-->"+otherConnection.size());

                   System.out.println("Info:total连接数-->"+totalConn);

 

                }

            },dbBean.getLazyCheck(),dbBean.getPeriodCheck());

        }

    }

    @Override

    publicvoiddestroyLongTimeNotUseConn(){

        newTimer().schedule(newTimerTask(){

            @Override

            publicvoidrun(){

                try{

                   System.out.println("Info:--------------我们开始摧毁那些长时间不使用的空闲链接--------------------");

                   for(inti=0;i<freeConnection.size();i++){

                       ConnectionfreeConn=freeConnection.get(i);

                        if(isValid(freeConn)){

                            freeConnection.remove(freeConn);

                            threadLocal.remove();

                            System.out.println("Info:关闭的空闲链接是-->"+freeConn);

                           freeConn.close();   //需要先从当前线程中移除conn后,再关闭链接。

                       }

                   }

                   System.out.println("Info:我们开始摧毁那些长时间不使用的其他链接。");

                   for(intj=0;j<otherConnection.size();j++){

                        ConnectionotherConn=otherConnection.get(j);

                       if(isValid(otherConn)){

                            otherConnection.remove(otherConn);

                            threadLocal.remove();

                            System.out.println("Info:关闭的其他链接是-->"+otherConn);

                            otherConn.close();  //需要先从当前线程中移除conn后,再关闭链接。

                       }

                   }

                }catch(ExceptiondestoryExp){

                   System.out.println("Error:销毁空闲链接和其他链接发生错误了-->"+destoryExp.toString());

                }

 

                //我们需要还原连接池的状态。

                isActive=false;

                totalConn=activeConnection.size();

            }

        },dbBean.getDestroyConnTime(),dbBean.getDestroyConnTime());

    }

 

 

}

(4)配置文件加载类

packagecom.yjf.java.utils;

 

importcom.yjf.java.bean.DBInfo;

 

importjava.io.FileReader;

importjava.io.IOException;

importjava.util.Properties;

 

/**

 * Created by rooton 20170924.

 * Update date:

 * <p>

 * Time: 1:24 PM

 * Project:test-java

 * Package:com.yjf.java.utils

 * Describe :

 * <p>

 * Result of Test:test ok,test error

 * Command:

 * <p>

 * <p>

 * Email:  jifei.yang@ngaa.com.cn

 * StatusUsing online

 * Attention

 */

publicclassPropertiesHelpUtil{

 

    privateStringproPath="/db/phoenix-pool.properties";

 

    publicPropertiesHelpUtil(){}

 

    privatesynchronizedPropertiesgetAllProp(Stringpath){

        Propertiesproperties=newProperties();

        try{

            properties.load(PropertiesHelpUtil.class.getResourceAsStream(proPath));

            returnproperties;

        }catch(IOExceptionex){

            System.err.println("Readproperties error"+ex.toString()+"....................................................");

        }

        returnnull;

    }

 

    publicsynchronizedDBInfoinitDb(){

        Propertiesproperties=getAllProp(proPath);

        Stringuser=properties.getProperty("username");

        Stringpwd=properties.getProperty("password");

        Stringurl=properties.getProperty("url");

        StringdriverClassName=properties.getProperty("driverClassName");

        StringpoolName=properties.getProperty("poolName");

        IntegerinitConnections=Integer.parseInt(properties.getProperty("initConnections","2"));

        IntegermaxActiveConnections=Integer.parseInt(properties.getProperty("maxActiveConnections","30"));

        longconnectionTimeOut=Long.parseLong(properties.getProperty("connectionTimeOut","20000"));

        booleanisCurrentConnection=Boolean.parseBoolean(properties.getProperty("isCurrentConnection","true"));

        booleanisCheckPool=Boolean.parseBoolean(properties.getProperty("isCheckPool","true"));

        longlazyCheck=Long.parseLong(properties.getProperty("lazyCheck","30000"));

        longperiodCheck=Long.parseLong(properties.getProperty("periodCheck","30000"));

        longreleaseConnTime=Long.parseLong(properties.getProperty("releaseConnTime","60000"));

        longdestroyConnTime=Long.parseLong(properties.getProperty("destroyConnTime","600000"));

 

        returnnewDBInfo(driverClassName,url,user,pwd,poolName,initConnections,maxActiveConnections

                ,connectionTimeOut,isCurrentConnection,isCheckPool,lazyCheck,

                periodCheck,releaseConnTime,destroyConnTime);

    }

 

}

(5)连接池管理类

packagecom.yjf.java.utils;

importcom.yjf.java.bean.DBInfo;

importcom.yjf.java.core.IConnectionPool;

importcom.yjf.java.core.IConnectionPoolImpl;

 

importjava.sql.Connection;

 

importjava.util.concurrent.ConcurrentHashMap;

 

/**

 * Created by rooton 20170924.

 * Update date:

 * <p>

 * Time: 2:37 PM

 * Project:test-java

 * Package:com.yjf.java.utils

 * Describe :Connection pool management class.

 * <p>

 * Result of Test:test ok,test error

 * Command:

 * <p>

 * <p>

 * Email:  jifei.yang@ngaa.com.cn

 * StatusUsing online

 * Attention

 */

publicclassDBFactoryManager{

 

    // 连接池存放

    privateConcurrentHashMap<String,IConnectionPool>pools=newConcurrentHashMap<>();

 

    //初始化

    privateDBFactoryManager(){

        init();

    }

    //单例实现

    publicstaticDBFactoryManagergetInstance(){

        returnSingtonle.instance;

    }

    privatestaticclassSingtonle{

        privatestaticDBFactoryManagerinstance= newDBFactoryManager();

    }

    //初始化所有的连接池

    privatevoidinit(){

        DBInfobean=newPropertiesHelpUtil().initDb();

            IConnectionPoolImplpool=newIConnectionPoolImpl(bean);

        pools.put(bean.getPoolName(),pool);

        System.out.println("Info:成功初始化连接池-->"+bean.getPoolName());

    }

 

    //获得连接,根据连接池名字获得连接

    publicConnection getConnection(StringpoolName){

        Connectionconn=null;

        if(pools.size()>0&&pools.containsKey(poolName)){

            conn=getPool(poolName).getConnection();

        }else{

            System.err.println("Error:找不到这个连接池-->"+poolName);

        }

        returnconn;

    }

 

    //关闭,回收连接

    publicvoidclose(StringpoolName,Connectionconn){              

        IConnectionPoolpool=getPool(poolName);

        try{

            if(pool!=null){

                pool.releaseConn(conn);

            }

        }catch(Exceptione){

            System.out.println("Error:连接池已被销毁。");

            e.printStackTrace();

        }

    }

 

 

    //获得连接池

    publicIConnectionPoolgetPool(StringpoolName){

        IConnectionPoolpool=null;

        if(pools.size()>0){

            pool=pools.get(poolName);

        }

        returnpool;

    }

    //清空连接池

    publicvoiddestroy(StringpoolName){

        IConnectionPoolpool=getPool(poolName);

        if(pool!=null){

            System.out.println("Info:清空连接池。");

            pool.destroyFreeAndMoveToOther();

            pool.isActive(false);

        }

    }

 

 

}

 

(6)配置文件

url=jdbc:mysql://192.168.1.1:3306/mysql?characterEncoding=GBK

driverClassName=com.mysql.jdbc.Driver

username=root

password=123123

 

# Pool name .

poolName=mysqlPool

# Initialize the number of database connections.

initConnections=2

 

# The maximum number of connections allowed iscorresponding to the settings of the database.

maxActiveConnections=5

 

# whether to get the current connection, default true.

isCurrentConnection=true

# Do you need to check the connection pool regularly?

isCheckPool=true

 

############################Atention :destroyConnTime> lazyCheck(periodCheck) > releaseConnTime>connectionTimeOut #######

 

# How long will it take to destroy a link?.

destroyConnTime=37000

 

# How long does it take to start checking? Check thefrequency of database links.

lazyCheck=12000

periodCheck=12000

 

# How many milliseconds release a free link?

releaseConnTime=10000

 

# Repeat the frequency of the connection (inmilliseconds).

connectionTimeOut=50000

 

(7)测试类

packagecom.test.java.Thread;

 

importcom.yjf.java.core.IConnectionPool;

importcom.yjf.java.utils.DBFactoryManager;

 

importjava.sql.Connection;

importjava.util.Timer;

importjava.util.TimerTask;

 

 

/**

 * Created by rooton 20170924.

 * Update date:

 * <p>

 * Time: 4:53 PM

 * Project:test-java

 * Package:com.test.java.Thread

 * Describe :

 * <p>

 * Result of Test:test ok,test error

 * Command:

 * <p>

 * <p>

 * Email:  jifei.yang@ngaa.com.cn

 * StatusUsing online

 * Attention

 */

publicclassTestConn{

 

    privatestaticsynchronizedConnectiongetConn(DBFactoryManager mm){

        returnmm.getConnection("mysqlPool");

    }

 

    publicstaticvoidmain(String[]args)throwsException{

        Stringname="mysqlPool";

        DBFactoryManagerdbFactoryManager=DBFactoryManager.getInstance();

        IConnectionPool poll=dbFactoryManager.getPool(name);

 

        Threadth0=newThread(newRunnable(){

            @Override

            publicvoidrun(){

              for(inti=0;i<5;i++){

                  Connectioncd=getConn(dbFactoryManager);

                  System.out.println(i+"--th0-------->"+cd);

                  try{

                     Thread.sleep(10000);

                     dbFactoryManager.close(name,cd);

                  }catch(Exceptione){

                     e.printStackTrace();

                  }

 

              }

            }

        });

 

        Threadth1=newThread(newRunnable(){

            @Override

            publicvoidrun(){

                for(inti=0;i<4;i++){

                   Connectionconn=getConn(dbFactoryManager);

                   System.out.println(i+"--th1-------->"+conn);

                   try{

                        Thread.sleep(10000);

                       dbFactoryManager.close(name,conn);

                   }catch(Exceptione){

                       e.printStackTrace();

                   }

 

                }

            }

        });

 

        Threadth2=newThread(newRunnable(){

            @Override

            publicvoidrun(){

                for(inti=0;i<5;i++){

                   Connectioncn=getConn(dbFactoryManager);

                   System.out.println(i+"--th2-------->"+cn);

                   try{

                       Thread.sleep(10000);

                       poll.releaseConn(cn);

                   }catch(Exceptione){

                       e.printStackTrace();

                   }

 

                }

            }

        });

 

        Threadth3=newThread(newRunnable(){

            @Override

            publicvoidrun(){

                for(inti=0;i<5;i++){

                   Connectionconn=getConn(dbFactoryManager);

                   System.out.println(i+"--th3-------->"+conn);

                   try{

                       Thread.sleep(9000);

                       dbFactoryManager.close(name,conn);

                   }catch(Exceptione){

                       e.printStackTrace();

                    }

 

                }

            }

        });

 

        Threadth4=newThread(newRunnable(){

            @Override

            publicvoidrun(){

                for(inti=0;i<3;i++){

                   Connectionconn=getConn(dbFactoryManager);

                   System.out.println(i+"--th4-------->"+conn);

                   try{

                       Thread.sleep(12000);

                       dbFactoryManager.close(name,conn);

                   }catch(Exceptione){

                       e.printStackTrace();

                   }

 

                }

            }

        });

 

        th0.start();

        th1.start();

        th2.start();

        th3.start();

        th4.start();

        newTimer().schedule(newTimerTask(){

            @Override

            publicvoidrun(){

                for(inti=0;i<1;i++){

                   Connectionconn=getConn(dbFactoryManager);

                   System.out.println(i+"--schedule 01-------->"+conn);

                    try{

                       Thread.sleep(100);

                       dbFactoryManager.close(name,conn);

                   }catch(Exceptione){

                       e.printStackTrace();

                   }

 

                }

            }

        },10000,10000);

 

        newTimer().schedule(newTimerTask(){

            @Override

            publicvoidrun(){

                for(inti=0;i<1;i++){

                   Connectionconn=getConn(dbFactoryManager);

                   System.out.println(i+"--schedule 02-------->"+conn);

                   try{

                       Thread.sleep(100);

                       dbFactoryManager.close(name,conn);

                   }catch(Exceptione){

                       e.printStackTrace();

                   }

 

                }

            }

        },15000,15000);

    }

}

 

2、阿里巴巴的druid连接池

(1)配置文件(参考配置)

driverClassName=org.apache.phoenix.jdbc.PhoenixDriver

minIdle=2

initialSize=2

#最大连接池数量

maxActive=200

#获取连接时最大等待时间

maxWait=15000

testOnBorrow=false

testOnReturn=false

#如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效

testWhileIdle=true

timeBetweenEvictionRunsMillis=400000

validationQuery=select 'x'

validationQueryTimeout=1000

initConnectionSqls=select 'x'

 

#对于建立时间超过removeAbandonedTimeout的连接强制关闭 (destory time is 5 seconds)

removeAbandoned=true

removeAbandonedTimeout=300

 

 

poolPreparedStatements=true

#配置一个连接在池中最小生存的时间,单位是毫秒

minEvictableIdleTimeMillis=300000

 

(2)德鲁伊连接池管理类

packagecom.ngaa.webservice.utils;

 

importcom.alibaba.druid.pool.DruidDataSource;

importcom.alibaba.druid.pool.DruidDataSourceFactory;

importcom.alibaba.druid.pool.DruidPooledConnection;

importjava.io.InputStream;

importjava.io.Serializable;

importjava.sql.Connection;

importjava.sql.PreparedStatement;

importjava.sql.ResultSet;

importjava.sql.SQLException;

importjava.util.Properties;

importjava.util.Timer;

importjava.util.TimerTask;

 

importcom.ngaa.webservice.bean.common.pool.DBInfo;

importcom.ngaa.webservice.bean.common.pool.GlobalPathBean;

importorg.slf4j.Logger;

importorg.slf4j.LoggerFactory;

/**

 * Created by rooton 20171101.

 * Update date:

 * <p>

 * Time: 4:22 PM

 * Project:cdn-license-webservice

 * Package:com.ngaa.webservice.utils

 * Describe :

 * <p>

 * Result of Test:test ok,test error

 * Command:

 * <p>

 * <p>

 * Email:  jifei.yang@ngaa.com.cn

 * StatusUsing online

 * Attention

 */

 

publicclassDBConnectionFactoryimplementsSerializable{

    privatestaticLoggerlogger=LoggerFactory.getLogger(DBConnectionFactory.class);

    privatestaticDBConnectionFactorydbConnectFactory=null;

    privatestaticDruidDataSourcedataSource=null;

    final  staticDBInfodbInfo=newPropertiesHelpUtil().initDb();

    publicDBConnectionFactory()

    {

        this.dataSource=initDataSource();

//       this.closeAllConn();

    }

 

    publicstaticsynchronizedDBConnectionFactorygetDBConnectFactory()

    {

        logger.warn("connection;get connect Factory...........................");

        if(null==dbConnectFactory||dataSource.isClosed()){

            dbConnectFactory=newDBConnectionFactory();

            logger.warn("connectionis null ; get connect Factory again...........................");

        }

        logger.warn("returnconnection factory..................................");

        returndbConnectFactory;

    }

 

    publicConnectiongetConnection()

    {

        DruidPooledConnectionconnection=null;

        if(this.dataSource!=null){

            try

            {

                logger.warn("connection;before get the datasource .......................");

                connection=this.dataSource.getConnection();

                logger.warn("connection;dataSource url:{}",connection.getMetaData().getURL());

            }

            catch(SQLExceptione)

            {

                thrownewRuntimeException(e);

            }

        }else{

            logger.error("connection;data source not init ..............................");

        }

        returnconnection;

    }

 

    publicvoiddestoryDataSource()

    {

        if(this.dataSource!=null)

        {

            this.dataSource.close();

            logger.warn("connection;data source pool is closed...........................");

        }

        else

        {

            logger.warn("connection;data source is not init ,so can not close the pool...");

        }

    }

 

    privateDruidDataSourceinitDataSource()

    {

        InputStreaminput=null;

        try

        {

            logger.warn("Connection;start load the file of properties......................");

            PropertiesdbProp=newProperties();

            input=getClass().getResourceAsStream(GlobalPathBean.PHOENIX_PROPERTIES_PATH);

            dbProp.load(input);

            Stringurl="jdbc:phoenix:"+dbInfo.getQuorum()+":/hbase:"+dbInfo.getUsername()+":"+dbInfo.getKeyPath();

            logger.warn("url is{}",url);

            dbProp.setProperty("url",url);

            NgaaSafetyInitUtils.autherLogin(dbInfo.getQuorum(),dbInfo.getKrb5(),dbInfo.getUsername(),dbInfo.getKeyPath());

            DruidDataSourcedruidDataSource=(DruidDataSource)DruidDataSourceFactory.createDataSource(dbProp);

            logger.warn("connection;the time of max  waittime{}............................",druidDataSource.getMaxWait());

            logger.warn("connection;the number of max connection {} ........................",druidDataSource.getMaxActive());

            returndruidDataSource;

        }

        catch(Exceptionex)

        {

            logger.error("connection;load the file of properties is error,and create the data pollerror......................");

            thrownewRuntimeException(ex);

        }

    }

 

    publicstaticvoidreleaseConn(PreparedStatementpstm,ResultSetrs,Connectionconn)

            throwsSQLException

    {

        if(rs!=null){

            rs.close();

        }

        if(pstm!=null){

            pstm.close();

        }

        if(conn!=null){

            conn.close();

        }

    }

 

}


(3)测试获取链接和释放链接

// Get connection

  Connection connect =DBConnectionFactory.getDBConnectFactory().getConnection();

  System.out.println(connect);

  try {

    // Release connection.

   DBConnectionFactory.releaseConn(null, null,connect);

    } catch (SQLException e) {

           e.printStackTrace();

  }




应用场景是什么?

       连接池特别适用于在连接请求被丢弃或延迟的高负载环境中优化性能。这种情况对应用程序的整体性能有不利的影响。实际上,在创建JDBC Web或企业应用程序时,出于所有实际的原因始终使用连接池。第三方库非常稳定,能够提供他们稳定的东西,理解连接池的概念并能够实现它们是所有JDBC程序员必须的,但是不推荐使用自己定义的连接池,只能自己玩着测试使用,不可生产环境上应用。。。



参考

(1)德鲁伊官方:https://github.com/alibaba/druid

(2)博客:

http://www.snaq.net/java/DBPool/

https://www.developer.com/java/data/understanding-jdbc-connection-pooling.html

http://greemranqq.iteye.com/blog/1969273

 

感谢以下两位的支持:

http://my.csdn.net/gogogogood

http://my.csdn.net/Sosog_Jung

 

 

 

 

 

 

 


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
Spring Boot是一个用于简化Spring应用开发的框架,而Druid是一个高效的数据库连接池。在Spring Boot项目中使用Druid连接池可以提供高性能的数据库连接管理和监控功能。 要在Spring Boot中使用Druid连接池,需要以下步骤: 1. 在项目的pom.xml文件中添加Druid依赖: ```xml <dependencies> <!-- Spring Boot Starter JDBC --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- Druid依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> </dependencies> ``` 2. 在application.properties或application.yml文件中配置Druid连接池相关属性,例如: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver # Druid连接池配置 spring.datasource.druid.initial-size=5 spring.datasource.druid.min-idle=5 spring.datasource.druid.max-active=20 spring.datasource.druid.max-wait=60000 spring.datasource.druid.time-between-eviction-runs-millis=60000 spring.datasource.druid.min-evictable-idle-time-millis=300000 spring.datasource.druid.validation-query=SELECT 1 spring.datasource.druid.test-while-idle=true spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false spring.datasource.druid.filters=stat spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20 spring.datasource.druid.use-global-data-source-stat=true ``` 3. 在启动类上添加`@EnableTransactionManagement`和`@MapperScan`注解,例如: ```java @SpringBootApplication @EnableTransactionManagement @MapperScan("com.example.mapper") public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } ``` 以上是在Spring Boot项目中使用Druid连接池的基本配置步骤,你可以根据自己的需求修改配置参数来满足具体业务场景。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

往事随风ing

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值