1. 程式人生 > >資料庫連線池的原理與實現(詳解)

資料庫連線池的原理與實現(詳解)

資料庫連線池類的設計
類1:資料庫連線池類DBconnctionPool
屬性:
inuserd 當前正在使用的連線數(int 型別)
maxConn 最大的連線數(int 型別)
minConn 最小的連線數(int 型別)
poolName 連線池的名稱(String 型別)
ArrayList freeConnections=new ArrayList() (容器,用來裝空閒的連線)
username 使用者名稱(String型別)
password 密碼(String 型別)
url 連線的地址(String 型別)
driver 驅動(String型別)
方法:
1.構造方法
//構造器函式
public DBconnctionPool(int maxConn, String username, String password,
        String url, String driver) {
    super();
    this.maxConn = maxConn;
    this.username = username;
    this.password = password;
    this.url = url;
    this.driver = driver;
}
2.用完釋放連線的方法
public synchronized void freeConnection(Connection conn){
    freeConnections.add(conn);
    inuserd--;
}
3.建立新連線的方法
public Connection createConnection() {
    Connection conn = null;
    try {
        Class.forName(driver);
        conn = DriverManager.getConnection(url, username, password);
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        System.out.println("sorry,can't find the driver");
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        System.out.println("can't connect...");
    }
    return conn;
}
4.從連線池得到連線的方法
public synchronized Connection getConnection()
 {
  Connection con=null;
  if(this.freeConnections.size()>0)
  {
   con=(Connection)this.freeConnections.get(0);
   this.freeConnections.remove(0);//如果連線分配出去了,就從空閒連線裡刪除
   if(con==null)con=getConnection(); //繼續獲得連線
  }
  else
  {
   con=newConnection(); //新建連線
  }
  if(this.maxConn==0||this.maxConn<this.inUsed)
  {
   con=null;//等待 超過最大連線時
  }
  if(con!=null)
  {
   this.inUsed++;
   System.out.println("得到 "+this.name+" 的連線,現有"+inUsed+"個連線在使用!");
  }
  return con;
 }
 5.釋放所有空閒連線的方法
 public synchronized void release(){
    Iterator allconns=freeConnections.iterator();
    while(allconns.hasNext()){
        Connection conn=(Connection) allconns.next();
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //移除集合裡的所有元素
    freeConnections.clear();
}

類2:資料庫連線池管理類
package com.crm.util.pool;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

/**
 * 資料庫連線池管理類
 * @author abcd
 *
 */
public class DBconnectionManager {
    public int clients;//客戶的連線數
    static private DBconnectionManager instance;//唯一的連線池管理類例項
    HashMap<String,DBconnctionPool> connectPools=new HashMap<String,DBconnctionPool>(); 
    
    ArrayList<DsconfigBean> drivers=new ArrayList<DsconfigBean>();//bean類集合
    
    /**
     * 利用單例模式保證取得唯一的連線池管理類例項
     * @return
     */
    static public DBconnectionManager getInstance(){
        if(instance==null){
            instance=new DBconnectionManager();
        }
        return instance;
    }
    /**
     * 建立連線池
     * @param bean
     */
    public void createPool(DsconfigBean bean){
        
        DBconnctionPool pool=new DBconnctionPool();
        System.out.println(bean.getName());
        pool.setDriver(bean.getDriver());
        pool.setMaxConn(bean.getMaxCount());
        pool.setPassword(bean.getPassword());
        pool.setPoolName(bean.getName());
        pool.setUrl(bean.getUrl());
        pool.setUsername(bean.getUsername());
        connectPools.put(bean.getName(), pool);
    }
    /**
     * 載入驅動程式
     */
    public void loadDrivers(){
        ParseConfig oaConfig=new ParseConfig();
        drivers=oaConfig.ReadConfig();
        
    }
    /**
     * 初始化連線池引數
     * 1.呼叫類讀取配置檔案
     * 2.把讀取到的有關driver的資訊儲存在集合drivers裡
     */
    public void init(){
        loadDrivers();
        //遍歷迭代建立相應的連線池
        DsconfigBean myBean=new DsconfigBean();
        
        for(int i=0;i<drivers.size();i++){
            myBean=drivers.get(i);
            createPool(myBean);
        }
        
    }
    /**
     * 根據連線池的名字得到一個連線
     * @param name
     * @return
     */
    public Connection getConnection(String name){
        DBconnctionPool pool=null;
        Connection conn=null;
        
        pool=(DBconnctionPool)connectPools.get(name);
        conn=pool.getConnection();
        return conn;
    }
    
    
}

類3:配置檔案對應的bean類
package com.crm.util.pool;
/**
 * 配置檔案Bean類
 * @author abcd
 *
 */
public class DsconfigBean {
    private String name;//資料庫名字
    private String type;//連線池型別
    private String driver;//連線池驅動
    private String url;//連線池地址
    private String username;//使用者名稱
    private String password;//密碼
    private int maxCount;//最大連線數
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getDriver() {
        return driver;
    }
    public void setDriver(String driver) {
        this.driver = driver;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public int getMaxCount() {
        return maxCount;
    }
    public void setMaxCount(int maxCount) {
        this.maxCount = maxCount;
    }
    
}

類4:解析新增配置檔案的類
package com.crm.util.pool;

import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * 操作配置檔案的類
 * @author abcd
 *
 */
public class ParseConfig {
    /**
     * 利用dom4j包讀取配置檔案內容返回集合beans
     * @return
     */
    public  ArrayList<DsconfigBean> ReadConfig(){
        ArrayList<DsconfigBean> beans=new ArrayList<DsconfigBean>();
        //得到解析器
        SAXReader saxReader=new SAXReader();
        //設定ErrorHander
        saxReader.setErrorHandler(new DefaultHandler(){
            public void error(SAXParseException ex){
                System.out.println(ex.getSystemId()+"文件的第"+ex.getLineNumber()+"行,第"+
                        ex.getColumnNumber()+"列"+"發生錯誤"+ex.getMessage());
            }
        });
        //建立樹形結構開始解析
        try {
            Document document=saxReader.read("dsconfig.xml");
            Element root=document.getRootElement();//得到根節點
            //獲得所有的pool下的節點
            List<Node> nodes=document.selectNodes("ds-config/pool");
            //System.out.println(nodes.size());
            //遍歷節點
            for (Node node : nodes) {
                DsconfigBean dsconfigBean=new DsconfigBean();
                Node node1=node.selectSingleNode("driver");
                Node node2=node.selectSingleNode("username");
                Node node3=node.selectSingleNode("password");
                Node node4=node.selectSingleNode("url");
                Node node5=node.selectSingleNode("maxconn");
                Node node6=node.selectSingleNode("type");
                dsconfigBean.setDriver(node1.getStringValue());
                dsconfigBean.setUsername(node2.getStringValue());
                dsconfigBean.setPassword(node3.getStringValue());
                dsconfigBean.setUrl(node4.getStringValue());
                dsconfigBean.setMaxCount(Integer.valueOf(node5.getStringValue()));
                dsconfigBean.setName(node6.getStringValue());
                beans.add(dsconfigBean);
    
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return beans;
        
    }
}
5.配置檔案dsconfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<ds-config>
<pool>
<type>mysql</type>
<name>user</name>
<driver>com.mysql.jdbc.driver</driver>
<url>jdbc:mysql://localhost:3306/user</url>
<username>sa</username>
<password>123456</password>
<maxconn>100</maxconn>
</pool>

<pool>
<type>mysql</type>
<name>user2</name>
<driver>com.mysql.jdbc.driver</driver>
<url>jdbc:mysql://localhost:3306/user2</url>
<username>sa</username>
<password>1234</password>
<maxconn>10</maxconn>
</pool>
<pool>
<type>sqlserver</type>
<name>books</name>
<driver>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver>
<url>jdbc:sqlserver://localhost:1433;DatabaseName=GZLCRM</url>
<username>sa</username>
<password>123</password>
<maxconn>100</maxconn>
</pool>
</ds-config>
6.測試類DBTest
package com.crm.util.pool;

import java.sql.Connection;

/**
 * 測試連線池的類
 * @author abcd
 *
 */
public class DBTest {
    public static void main(String[] args) {
        DBconnectionManager manager=DBconnectionManager.getInstance();
        manager.init();
        Connection connection=manager.getConnection("sqlserver");
        System.out.println(connection.toString());
    }
}