连接池实现代码

 

1、连接池模型
本文讨论的连接池包括一个连接池类(DBConnectionPool)和一个连接池管理类 (DBConnetionPoolManager)。
——连接池类是连接的“缓冲池”:
①从连接池获取或创建可用连接;
② 使用完毕之后,把连接返还给连接池;
在系统关闭前,断开所有连接并释放连接占用的系统资源;
④还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。
 
 
连接池管理类是连接池类的外覆类(wrapper),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理:
①装载并注册特定数据库的JDBC驱动程序;
②根据属性文件给定的信息,创建连接池对象;
③为方便管理多个连接池对象,为每一个连接池 对象取一个名字,实现连接池名字与其实例之间的映射;
④跟踪客户使用连接情况,以便需要时关闭连接释放资源。
 
连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于安全性问题,需要不同的用户使用不同的名称和密码。
public class DBConnectionPool implements TimerListener{  
        private int checkedOut;//已被分配出去的连接数  
        private ArrayList freeConnections=new ArrayList();   //空闲池,根据创建时间顺序存放已创建但尚未分配出去的连接
 
        private int minConn;//连接池里连接的最小数量  
        private int maxConn;//连接池里允许存在的最大连接数  
 
        private String name;//为这个连接池取个名字,方便管理  
        private String password;//连接数据库时需要的密码  
        private String url;//所要创建连接的数据库的地址  
        private String user;//连接数据库时需要的用户名  
        public Timer timer;//定时器
 
【关键接口】
        public DBConnectionPool(String name,String URL,String user,   String password,int maxConn)//公开的构造函数  
 
        public synchronized void freeConnection(Connection con)  //使用完毕之后,把连接返还给空闲池  
        public synchronized Connection getConnection(long timeout)  //得到一个连接,timeout是等待时间  
        public synchronized void release() //断开所有连接,释放占用的系统资源  
        private Connection newConnection() //新建一个数据库连接  
        public synchronized void TimerEvent()  {//定时器事件处理函数  }  
 
 
public class DBConnectionManager {  
static private DBConnectionManager instance;  //连接池管理类的唯一实例  
static private int clients;//客户数量  
private ArrayList drivers=new ArrayList();  //容器,存放数据库驱动程序  
private HashMap pools = new HashMap();  //以name/value的形式存取连接池对象的名字及连接池对象  
static synchronized public DBConnectionManager getInstance()  /**如果instance已经创建,直接返回这个实例;否则,调用私有构造函数,创建连接池管理类的唯一实例*/  
private DBConnectionManager() //私有构造函数,在其中调用初始化函数init()  
public void freeConnection(String name,Connection con)  //释放一个连接,name是一个连接池对象的名字  
public Connection getConnection(String name)  //从名字为name的连接池对象中得到一个连接  
public Connection getConnection(String name,long time)  //从名字为name的连接池对象中取得一个连接,time是等待时间  
public synchronized void release()//释放所有资源  
private void createPools(Properties props)  //根据属性文件提供的信息,创建一个或多个连接池  
private void init()//初始化连接池管理类的唯一实例,由私有构造函数调用  
private void loadDrivers(Properties props)//装载数据库驱动程序 
}

 
    1. package book.util;  
    2. import java.sql.Connection;  
    3. import java.sql.DatabaseMetaData;  
    4. import java.sql.Date;  
    5. import java.sql.Driver;  
    6. import java.sql.DriverManager;  
    7. import java.sql.PreparedStatement;  
    8. import java.sql.ResultSet;  
    9. import java.sql.SQLException;  
    10. import java.sql.Statement;  
    11. import java.util.Vector;  
    12. public class Pool {  
    13.     public static void main(String[] args) {  
    14.         Pool pool = new Pool("com.microsoft.sqlserver.jdbc.SQLServerDriver","jdbc:sqlserver://localhost:1433;DataBaseName=Book","sa","aaaaaa");  
    15.         try {  
    16.             pool.createConnections(4);                
    17.         } catch (SQLException e) {  
    18.             e.printStackTrace();  
    19.         }  
    20.         Connection conn = pool.getConnection();   
    21.         try {  
    22.             String sql = "select * from allbook";  
    23.             PreparedStatement ps;  
    24.             ps = conn.prepareStatement(sql);  
    25.             ResultSet rs=ps.executeQuery();  
    26.             while(rs.next()){  
    27.                 System.out.println(rs.getString("BOOKNAME"));  
    28.             }  
    29.         } catch (SQLException e) {  
    30.             // TODO Auto-generated catch block  
    31.             e.printStackTrace();  
    32.         }finally{  
    33.             pool.returnConnection(conn);  
    34.         }  
    35.         //long startTime=System.currentTimeMillis();
    36.         //long endTime=System.currentTimeMillis();   
    37.         //System.out.println("程序运行时间: "+(endTime-startTime)+"ms");   
    38.     }  
    39.       
    40.     private String jdbcDriver = "";//数据库驱动  
    41.     private String dbUrl = "";//数据库url  
    42.     private String dbUsername = "";//数据库用户名  
    43.     private String dbPassword = "";//数据库密码  
    44.     private String testTable = "";  
    45.     private int initialConnectionsNum = 10;//连接池初始连接数  
    46.     private int maxConnectionsNum = 50;//连接池最大连接数  
    47.     private int incrementalConnections = 5;//每次动态添加的连接数  
    48.     private Vector<PooledConnection> connections = null;//向量,存放连接池中的连接,初始为空  
    49.       
    50.     /*无参构造函数*/  
    51.     public Pool()  
    52.     {}  
    53.       
    54.     /*带参数的构造函数 
    55.      * 初始化数据库驱动、数据库url、数据库用户名、数据库密码、测试表 
    56.      * */  
    57.     public Pool(String driver, String url, String name, String pass)  
    58.     {  
    59.         this.jdbcDriver = driver;  
    60.         this.dbUrl = url;  
    61.         this.dbUsername = name;  
    62.         this.dbPassword = pass;  
    63.         //this.testTable = table;  
    64.         try {  
    65.             this.createPool();  
    66.         } catch (InstantiationException e) {  
    67.             // TODO Auto-generated catch block  
    68.             e.printStackTrace();  
    69.         } catch (IllegalAccessException e) {  
    70.             // TODO Auto-generated catch block  
    71.             e.printStackTrace();  
    72.         } catch (ClassNotFoundException e) {  
    73.             // TODO Auto-generated catch block  
    74.             e.printStackTrace();  
    75.         } catch (SQLException e) {  
    76.             // TODO Auto-generated catch block  
    77.             e.printStackTrace();  
    78.         }  
    79.     }  
    80.       
    81.     /*函数,创建连接池*/  
    82.     public synchronized void createPool()   
    83.     throws InstantiationException, IllegalAccessException,   
    84.     ClassNotFoundException, SQLException  
    85.     {  
    86.         /*确保连接池为创建,如果已经创建,则保存连接的向量不为空 
    87.          * */  
    88.         if (this.connections != null)  
    89.         {  
    90.             return ;  
    91.         }  
    92.         //驱动器实例化  
    93.         Driver driver = (Driver)(Class.forName(this.jdbcDriver).newInstance());  
    94.         //注册驱动器  
    95.         DriverManager.registerDriver(driver);
    96.         //创建保存连接的向量  
    97.         this.connections = new Vector<PooledConnection>();  
    98.         //创建数据库连接  
    99.         this.createConnections(this.initialConnectionsNum);  
    100.     }  
    101.       
    102.     /*函数,创建数据库连接 
    103.      * */  
    104.     private void createConnections (int num) throws SQLException  
    105.     {  
    106.         /*循环创建连接 
    107.          * 需要首先检查当前连接数是否已经超出连接池最大连接数 
    108.          * */  
    109.         for (int i = 0; i < num; ++i)  
    110.         {  
    111.             //检查  
    112.             if (this.connections.size() >= this.maxConnectionsNum)  
    113.             {  
    114.                 return;  
    115.             }  
    116.             //创建单个连接  
    117.             this.connections.addElement  
    118.             (new PooledConnection(newConnection()));  
    119.         }  
    120.           
    121.     }  
    122.       
    123.     /*函数,创建一个数据库连接*/  
    124.     private Connection newConnection() throws SQLException  
    125.     {  
    126.         /*创建连接*/  
    127.         Connection con = DriverManager.getConnection(this.dbUrl,   
    128.                 this.dbUsername, this.dbPassword);  
    129.         /*如果是第一次创建连接,则检查所连接的数据库的允许最大连接数是否小于 
    130.          * 我们所设定的最大连接数*/  
    131.         if (this.connections.size() == 0)  
    132.         {  
    133.             DatabaseMetaData metadata = con.getMetaData();  
    134.             //得到数据库最大连接数  
    135.             int dbMaxConnectionsNum = metadata.getMaxConnections();  
    136.             //如果数据库最大连接数更小,则更改我们所设定的连接池最大连接数  
    137.             if (dbMaxConnectionsNum > 0   
    138.                     && this.maxConnectionsNum > dbMaxConnectionsNum)  
    139.             {  
    140.                 this.maxConnectionsNum = dbMaxConnectionsNum;  
    141.             }  
    142.         }  
    143.         return con;  
    144.     }  
    145.       
    146.     /*函数,得到一个可用连接 
    147.      * */  
    148.     public synchronized Connection getConnection ()   
    149.     {  
    150.         Connection con = null;  
    151.         /*检查连接池是否已经建立*/  
    152.         if (this.connections == null)  
    153.         {  
    154.             return con;  
    155.         }  
    156.         //得到一个可用连接  
    157.         try {  
    158.             con = this.getFreeConnection();  
    159.         } catch (SQLException e) {  
    160.             // TODO Auto-generated catch block  
    161.             e.printStackTrace();  
    162.         }  
    163.         //如果未找到合适连接,循环等待、查找,直到找到合适连接  
    164.         while(con == null)  
    165.         {  
    166.             this.wait(30);  
    167.             try {  
    168.                 con = this.getFreeConnection();  
    169.             } catch (SQLException e) {  
    170.                 // TODO Auto-generated catch block  
    171.                 e.printStackTrace();  
    172.             }  
    173.         }  
    174.           
    175.         return con;  
    176.     }  
    177.       
    178.       
    179.     /*函数,得到一个可用连接*/  
    180.     private Connection getFreeConnection() throws SQLException  
    181.     {  
    182.         Connection con = null;  
    183.         //查找一个可用连接  
    184.         con = this.findFreeConnection();  
    185.         //如果未找到可用连接,就建立一些新的连接,再次查找  
    186.         if (con == null)  
    187.         {  
    188.             this.createConnections(this.incrementalConnections);  
    189.             //再次查找  
    190.             con = this.findFreeConnection();  
    191.         }  
    192.         return con;  
    193.     }  
    194.       
    195.       
    196.     /*函数,从现有连接中查找一个可用连接 
    197.      * 在现有的连接中(向量connections中)找到一个空闲连接, 
    198.      * 并测试这个链接是否可用,若不可用则重新建立连接,替换原来的连接*/  
    199.     private Connection findFreeConnection () throws SQLException  
    200.     {  
    201.         Connection con = null;  
    202.         for (int i = 0; i < this.connections.size(); ++i)  
    203.         {  
    204.             PooledConnection pol = (PooledConnection)this.connections.get(i);  
    205.             if (!pol.isBusy())  
    206.             {  
    207.                 /*如果此链接未被使用,则返回这个连接并,设置正在使用标志*/  
    208.                 con = pol.getCon();  
    209.                 pol.setBusy(true);  
    210.                 /*测试连接是否可用*/  
    211.                 if (!this.testCon(con))  
    212.                 {  
    213.                     con = this.newConnection();  
    214.                     pol.setCon(con);  
    215.                 }  
    216.                 break;  
    217.             }  
    218.         }  
    219.         return con;  
    220.     }  
    221.       
    222.     /*函数,测试连接是否可用 
    223.      * */  
    224.     private boolean testCon (Connection con)  
    225.     {  
    226.         boolean useable = true;  
    227.         try  
    228.         {  
    229.             Statement st = con.createStatement();  
    230.             ResultSet rs = st.executeQuery("select count(*) from " + this.testTable);  
    231.             rs.next();  
    232.         }  
    233.         catch(SQLException e)  
    234.         {  
    235.             /*上面抛出异常,连接不可用,关闭*/  
    236.             useable = false;  
    237.             this.closeConnection(con);  
    238.         }  
    239.         return useable;  
    240.     }  
    241.       
    242.     /*函数,将使用完毕的连接放回连接池中 
    243.      * */  
    244.     public void returnConnection(Connection con)  
    245.     {  
    246.         /*确保连接池存在*/  
    247.         if (this.connections == null)  
    248.         {  
    249.             return ;  
    250.         }  
    251.         for (int i = 0; i < this.connections.size(); ++i)  
    252.         {  
    253.             PooledConnection pool = this.connections.get(i);  
    254.             //找到相应连接,设置正在使用标志为false  
    255.             if (con == pool.getCon())  
    256.             {  
    257.                 pool.setBusy(false);  
    258.             }  
    259.         }  
    260.           
    261.     }  
    262.       
    263.     /*函数,刷新连接池中的连接*/  
    264.     public synchronized void refreshConneciontPool () throws SQLException  
    265.     {  
    266.         /*确保连接池存在*/  
    267.         if (this.connections == null)  
    268.         {  
    269.             return ;  
    270.         }  
    271.         for (int i = 0; i < this.connections.size(); ++i)  
    272.         {  
    273.             PooledConnection pool = this.connections.get(i);  
    274.             if (pool.isBusy())  
    275.             {  
    276.                 this.wait(5000);  
    277.             }  
    278.             this.closeConnection(pool.getCon());  
    279.             pool.setCon(this.newConnection());  
    280.             pool.setBusy(false);  
    281.         }  
    282.     }  
    283.   
    284.     /*函数,关闭连接池*/  
    285.     public void closeConnectionPool()  
    286.     {  
    287.         /*确保连接池存在*/  
    288.         if (this.connections == null)  
    289.         {  
    290.             return ;  
    291.         }  
    292.         for (int i = 0; i < this.connections.size(); ++i)  
    293.         {  
    294.             PooledConnection pool = this.connections.get(i);  
    295.             if (pool.isBusy())  
    296.             {  
    297.                 this.wait(5000);  
    298.             }  
    299.             this.closeConnection(pool.getCon());  
    300.             this.connections.remove(i);  
    301.         }  
    302.         this.connections = null;  
    303.     }  
    304.       
    305.     /*函数,暂时无可用连接,进入等待队列等待m秒,再试 
    306.      * */  
    307.     private void wait(int mSecond)  
    308.     {  
    309.         try {  
    310.             Thread.sleep(mSecond);  
    311.         } catch (InterruptedException e) {  
    312.             // TODO Auto-generated catch block  
    313.             e.printStackTrace();  
    314.         }  
    315.     }  
    316.       
    317.     /** 
    318.      * @return the jdbcDriver 
    319.      */  
    320.     public String getJdbcDriver() {  
    321.         return jdbcDriver;  
    322.     }  
    323.   
    324.     /** 
    325.      * @param jdbcDriver the jdbcDriver to set 
    326.      */  
    327.     public void setJdbcDriver(String jdbcDriver) {  
    328.         this.jdbcDriver = jdbcDriver;  
    329.     }  
    330.   
    331.     /** 
    332.      * @return the dbUrl 
    333.      */  
    334.     public String getDbUrl() {  
    335.         return dbUrl;  
    336.     }  
    337.   
    338.     /** 
    339.      * @param dbUrl the dbUrl to set 
    340.      */  
    341.     public void setDbUrl(String dbUrl) {  
    342.         this.dbUrl = dbUrl;  
    343.     }  
    344.   
    345.     /** 
    346.      * @return the dbUsername 
    347.      */  
    348.     public String getDbUsername() {  
    349.         return dbUsername;  
    350.     }  
    351.   
    352.     /** 
    353.      * @param dbUsername the dbUsername to set 
    354.      */  
    355.     public void setDbUsername(String dbUsername) {  
    356.         this.dbUsername = dbUsername;  
    357.     }  
    358.   
    359.     /** 
    360.      * @return the dbPassword 
    361.      */  
    362.     public String getDbPassword() {  
    363.         return dbPassword;  
    364.     }  
    365.   
    366.     /** 
    367.      * @param dbPassword the dbPassword to set 
    368.      */  
    369.     public void setDbPassword(String dbPassword) {  
    370.         this.dbPassword = dbPassword;  
    371.     }  
    372.   
    373.     /** 
    374.      * @return the testTable 
    375.      */  
    376.     public String getTestTable() {  
    377.         return testTable;  
    378.     }  
    379.   
    380.     /** 
    381.      * @param testTable the testTable to set 
    382.      */  
    383.     public void setTestTable(String testTable) {  
    384.         this.testTable = testTable;  
    385.     }  
    386.   
    387.     /** 
    388.      * @return the initialConnectionsNum 
    389.      */  
    390.     public int getInitialConnectionsNum() {  
    391.         return initialConnectionsNum;  
    392.     }  
    393.   
    394.     /** 
    395.      * @param initialConnectionsNum the initialConnectionsNum to set 
    396.      */  
    397.     public void setInitialConnectionsNum(int initialConnectionsNum) {  
    398.         this.initialConnectionsNum = initialConnectionsNum;  
    399.     }  
    400.   
    401.     /** 
    402.      * @return the maxConnectionsNum 
    403.      */  
    404.     public int getMaxConnectionsNum() {  
    405.         return maxConnectionsNum;  
    406.     }  
    407.   
    408.     /** 
    409.      * @param maxConnectionsNum the maxConnectionsNum to set 
    410.      */  
    411.     public void setMaxConnectionsNum(int maxConnectionsNum) {  
    412.         this.maxConnectionsNum = maxConnectionsNum;  
    413.     }  
    414.   
    415.     /** 
    416.      * @return the incrementalConnections 
    417.      */  
    418.     public int getIncrementalConnections() {  
    419.         return incrementalConnections;  
    420.     }  
    421.   
    422.     /** 
    423.      * @param incrementalConnections the incrementalConnections to set 
    424.      */  
    425.     public void setIncrementalConnections(int incrementalConnections) {  
    426.         this.incrementalConnections = incrementalConnections;  
    427.     }  
    428.   
    429.     /** 
    430.      * @return the connections 
    431.      */  
    432.     public Vector<PooledConnection> getConnections() {  
    433.         return connections;  
    434.     }  
    435.   
    436.     /** 
    437.      * @param connections the connections to set 
    438.      */  
    439.     public void setConnections(Vector<PooledConnection> connections) {  
    440.         this.connections = connections;  
    441.     }  
    442.   
    443.     /*函数,连接使用完毕,关闭连接*/  
    444.     private void closeConnection (Connection con)  
    445.     {  
    446.         try  
    447.         {  
    448.             con.close();  
    449.         }  
    450.         catch(SQLException e)  
    451.         {  
    452.             e.printStackTrace();  
    453.         }  
    454.     }  
    455.       
    456.       
    457.     /*内部使用的保存数据库连接的类 
    458.      * 两个成员变量:连接、是否正在使用*/  
    459.     class PooledConnection  
    460.     {  
    461.         private Connection con = null;//连接  
    462.         private boolean busy = false;//是否正在使用,默认为非  
    463.           
    464.         /*构造函数*/  
    465.         public PooledConnection(Connection con)  
    466.         {  
    467.             this.con = con;  
    468.         }  
    469.   
    470.         /** 
    471.          * @return the con 
    472.          */  
    473.         public Connection getCon() {  
    474.             return con;  
    475.         }  
    476.   
    477.         /** 
    478.          * @param con the con to set 
    479.          */  
    480.         public void setCon(Connection con) {  
    481.             this.con = con;  
    482.         }  
    483.   
    484.         /** 
    485.          * @return the busy 
    486.          */  
    487.         public boolean isBusy() {  
    488.             return busy;  
    489.         }  
    490.   
    491.         /** 
    492.          * @param busy the busy to set 
    493.          */  
    494.         public void setBusy(boolean busy) {  
    495.             this.busy = busy;  
    496.         }  
    497.     }  
    498.   
    499. }  
posted @ 2015-07-08 23:20  Uncle_Nucky  阅读(189)  评论(0)    收藏  举报