近年來,隨著Internet/Intranet建網技術的飛速發展和在世界范圍內的迅速普及,計算機
應用程序已從傳統的桌面應用轉到Web應用?;贐/S(Browser/Server)架構的3層開發模式逐漸取代C/S(Client/Server)架構的開發模式,成為開發企業級應用和電子商務普遍采用的技術。在Web應用開發的早期,主要使用的技術是CGI﹑ASP﹑PHP等。之后,Sun公司推出了基于Java語言的Servlet+Jsp+JavaBean技術。相比傳統的開發技術,它具有跨平臺﹑安全﹑有效﹑可移植等特性,這使其更便于使用和開發。
Java應用程序訪問數據庫的基本原理
在Java語言中,JDBC(Java DataBase Connection)是應用程序與數據庫溝通的橋梁,
即Java語言通過JDBC技術訪問數據庫。JDBC是一種“開放”的方案,它為數據庫應用開發人員﹑數據庫前臺工具開發人員提供了一種標準的應用程序設計接口,使開發人員可以用純Java語言編寫完整的數據庫應用程序。JDBC提供兩種API,分別是面向開發人員的API和面向底層的JDBC驅動程序API,底層主要通過直接的JDBC驅動和JDBC-ODBC橋驅動實現與數據庫的連接。
一般來說,Java應用程序訪問數據庫的過程(如圖1所示)是:
?、傺b載數據庫驅動程序;
?、谕ㄟ^JDBC建立數據庫連接;
③訪問數據庫,執行SQL語句;
?、軘嚅_數據庫連接。

圖1 Java數據庫訪問機制
由上面的分析可以看出,問題的根源就在于對數據庫連接資源的低效管理。我們知道,

圖2 連接池的基本工作原理
在Java語言中,Connection類本身提供了對事務的支持,可以通過設置Connection的AutoCommit屬性為false,然后顯式的調用commit或rollback方法來實現。但要高效的進行Connection復用,就必須提供相應的事務支持機制??刹捎妹恳粋€事務獨占一個連接來實現,這種方法可以大大降低事務管理的復雜性。
連接池的實現
2、連接池實現(經過本人改版,可以適用多數據庫類型的應用以及一種數據庫類型多個數據庫且數據 庫的數量可以動態增加的應用程序)
1),DBConnectionPool.java 數據庫連接池類
2),DBConnectionManager .java 數據庫管理類
3),DSConfigBean .java 單個數據庫連接信息Bean
4),ParseDSConfig.java 操作多(這個'多'包括不同的數據庫和同一種數據庫有多個數據庫)
數據 配置文件xml
5),ds.config.xml 數據庫配置文件xml
原代碼如下:
DBConnectionPool.java
----------------------------------------------------------
/**
* 數據庫連接池類
*/
package com.chunkyo.db;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Timer;
* @author chenyanlin
*
*/
public class DBConnectionPool implements TimerListener {
private int inUsed=0; //使用的連接數
private ArrayList freeConnections = new ArrayList();//容器,空閑連接
private int minConn; //最小連接數
private int maxConn; //最大連接
private String name; //連接池名字
private String password; //密碼
private String url; //數據庫連接地址
private String driver; //驅動
private String user; //用戶名
public Timer timer; //定時
/**
*
*/
public DBConnectionPool() {
// TODO Auto-generated constructor stub
}
/**
* 創建連接池
* @param driver
* @param name
* @param URL
* @param user
* @param password
* @param maxConn
*/
public DBConnectionPool(String name, String driver,String URL, String user, String password, int maxConn)
{
this.name=name;
this.driver=driver;
this.url=URL;
this.user=user;
this.password=password;
this.maxConn=maxConn;
}
/**
* 用完,釋放連接
* @param con
*/
public synchronized void freeConnection(Connection con)
{
this.freeConnections.add(con);//添加到空閑連接的末尾
this.inUsed--;
}
/**
* timeout 根據timeout得到連接
* @param timeout
* @return
*/
public synchronized Connection getConnection(long timeout)
{
Connection con=null;
if(this.freeConnections.size()>0)
{
con=(Connection)this.freeConnections.get(0);
if(con==null)con=getConnection(timeout); //繼續獲得連接
}
else
{
con=newConnection(); //新建連接
}
if(this.maxConn==0||this.maxConn<this.inUsed)
{
con=null;//達到最大連接數,暫時不能獲得連接了。
}
if(con!=null)
{
this.inUsed++;
}
return con;
}
/**
*
* 從連接池里得到連接
* @return
*/
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;
}
/**
*釋放全部連接
*
*/
public synchronized void release()
{
Iterator allConns=this.freeConnections.iterator();
while(allConns.hasNext())
{
Connection con=(Connection)allConns.next();
try
{
con.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
this.freeConnections.clear();
}
/**
* 創建新連接
* @return
*/
private Connection newConnection()
{
try {
Class.forName(driver);
con=DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("sorry can't find db driver!");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println("sorry can't create Connection!");
}
return con;
}
/**
* 定時處理函數
*/
public synchronized void TimerEvent()
{
//暫時還沒有實現以后會加上的
}
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/**
* @return the driver
*/
public String getDriver() {
return driver;
}
/**
* @param driver the driver to set
*/
public void setDriver(String driver) {
this.driver = driver;
}
/**
* @return the maxConn
*/
public int getMaxConn() {
return maxConn;
}
/**
* @param maxConn the maxConn to set
*/
public void setMaxConn(int maxConn) {
this.maxConn = maxConn;
}
/**
* @return the minConn
*/
public int getMinConn() {
return minConn;
}
/**
* @param minConn the minConn to set
*/
public void setMinConn(int minConn) {
this.minConn = minConn;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return the user
*/
public String getUser() {
return user;
}
/**
* @param user the user to set
*/
public void setUser(String user) {
this.user = user;
}
-------------------------------------------
DBConnectionManager .java
------------------------------------------
/**
* 數據庫連接池管理類
*/
package com.chunkyo.db;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
import com.chunkyo.db.DSConfigBean;
import com.chunkyo.db.DBConnectionPool;
* @author chenyanlin
*
*/
public class DBConnectionManager {
static private int clients; //客戶連接數
private Vector drivers = new Vector();//驅動信息
private Hashtable pools=new Hashtable();//連接池
/**
* 實例化管理類
*/
public DBConnectionManager() {
// TODO Auto-generated constructor stub
this.init();
}
/**
* 得到唯一實例管理類
* @return
*/
static synchronized public DBConnectionManager getInstance()
{
if(instance==null)
{
instance=new DBConnectionManager();
}
return instance;
}
/**
* 釋放連接
* @param name
* @param con
*/
public void freeConnection(String name, Connection con)
{
DBConnectionPool pool=(DBConnectionPool)pools.get(name);//根據關鍵名字得到連接池
if(pool!=null)
pool.freeConnection(con);//釋放連接
}
/**
* 得到一個連接根據連接池的名字name
* @param name
* @return
*/
public Connection getConnection(String name)
{
DBConnectionPool pool=null;
Connection con=null;
pool=(DBConnectionPool)pools.get(name);//從名字中獲取連接池
con=pool.getConnection();//從選定的連接池中獲得連接
if(con!=null)
System.out.println("得到連接。。。");
return con;
}
/**
* 得到一個連接,根據連接池的名字和等待時間
* @param name
* @param time
* @return
*/
public Connection getConnection(String name, long timeout)
{
DBConnectionPool pool=null;
Connection con=null;
pool=(DBConnectionPool)pools.get(name);//從名字中獲取連接池
con=pool.getConnection(timeout);//從選定的連接池中獲得連接
System.out.println("得到連接。。。");
return con;
}
/**
* 釋放所有連接
*/
public synchronized void release()
{
Enumeration allpools=pools.elements();
while(allpools.hasMoreElements())
{
DBConnectionPool pool=(DBConnectionPool)allpools.nextElement();
if(pool!=null)pool.release();
}
pools.clear();
}
* 創建連接池
* @param props
*/
private void createPools(DSConfigBean dsb)
{
DBConnectionPool dbpool=new DBConnectionPool();
dbpool.setName(dsb.getName());
dbpool.setDriver(dsb.getDriver());
dbpool.setUrl(dsb.getUrl());
dbpool.setUser(dsb.getUsername());
dbpool.setPassword(dsb.getPassword());
dbpool.setMaxConn(dsb.getMaxconn());
System.out.println("ioio:"+dsb.getMaxconn());
pools.put(dsb.getName(), dbpool);
}
/**
* 初始化連接池的參數
*/
private void init()
{
//加載驅動程序
this.loadDrivers();
//創建連接池
Iterator alldriver=drivers.iterator();
while(alldriver.hasNext())
{
this.createPools((DSConfigBean)alldriver.next());
System.out.println("創建連接池。。。");
}
System.out.println("創建連接池完畢。。。");
}
* 加載驅動程序
* @param props
*/
private void loadDrivers()
{
ParseDSConfig pd=new ParseDSConfig();
//讀取數據庫配置文件
drivers=pd.readConfigInfo("ds.config.xml");
System.out.println("加載驅動程序。。。");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
----------------------------------------
DSConfigBean.java
----------------------------------------
/**
* 配置文件Bean類
*/
package com.chunkyo.db;
* @author chenyanlin
*
*/
public class DSConfigBean {
private String name =""; //連接池名字
private String driver =""; //數據庫驅動
private String url =""; //數據庫url
private String username =""; //用戶名
private String password =""; //密碼
private int maxconn =0; //最大連接數
/**
*
*/
public DSConfigBean() {
// TODO Auto-generated constructor stub
}
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
* @return the driver
*/
public String getDriver() {
return driver;
}
* @param driver the driver to set
*/
public void setDriver(String driver) {
this.driver = driver;
}
* @return the maxconn
*/
public int getMaxconn() {
return maxconn;
}
* @param maxconn the maxconn to set
*/
public void setMaxconn(int maxconn) {
this.maxconn = maxconn;
}
* @return the name
*/
public String getName() {
return name;
}
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
* @return the password
*/
public String getPassword() {
return password;
}
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
* @return the type
*/
public String getType() {
return type;
}
* @param type the type to set
*/
public void setType(String type) {
this.type = type;
}
* @return the url
*/
public String getUrl() {
return url;
}
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}
* @return the username
*/
public String getUsername() {
return username;
}
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
-----------------------------------------------------
ParseDSConfig.java
-----------------------------------------------------
/**
* 操作配置文件類 讀 寫 修改 刪除等操作
*/
package com.chunkyo.db;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Vector;
import java.util.Iterator;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
* @author chenyanlin
*
*/
public class ParseDSConfig {
* 構造函數
*/
public ParseDSConfig() {
// TODO Auto-generated constructor stub
}
/**
* 讀取xml配置文件
* @param path
* @return
*/
public Vector readConfigInfo(String path)
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
Vector dsConfig=null;
FileInputStream fi = null;
try
{
fi=new FileInputStream(rpath);//讀取路徑文件
dsConfig=new Vector();
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(fi);
Element root=doc.getRootElement();
List pools=root.getChildren();
Element pool=null;
Iterator allPool=pools.iterator();
while(allPool.hasNext())
{
pool=(Element)allPool.next();
DSConfigBean dscBean=new DSConfigBean();
dscBean.setType(pool.getChild("type").getText());
dscBean.setName(pool.getChild("name").getText());
System.out.println(dscBean.getName());
dscBean.setDriver(pool.getChild("driver").getText());
dscBean.setUrl(pool.getChild("url").getText());
dscBean.setUsername(pool.getChild("username").getText());
dscBean.setPassword(pool.getChild("password").getText());
dscBean.setMaxconn(Integer.parseInt(pool.getChild("maxconn").getText()));
dsConfig.add(dscBean);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
fi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return dsConfig;
}
*修改配置文件 沒時間寫 過段時間再貼上去 其實一樣的
*/
public void modifyConfigInfo(String path,DSConfigBean dsb) throws Exception
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
FileInputStream fi=null; //讀出
FileOutputStream fo=null; //寫入
}
/**
*增加配置文件
*
*/
public void addConfigInfo(String path,DSConfigBean dsb)
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
FileInputStream fi=null;
FileOutputStream fo=null;
try
{
fi=new FileInputStream(rpath);//讀取xml流
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(fi); //得到xml
Element root=doc.getRootElement();
List pools=root.getChildren();//得到xml子樹
Element newpool=new Element("pool"); //創建新連接池
Element pooltype=new Element("type"); //設置連接池類型
pooltype.setText(dsb.getType());
newpool.addContent(pooltype);
Element poolname=new Element("name");//設置連接池名字
poolname.setText(dsb.getName());
newpool.addContent(poolname);
Element pooldriver=new Element("driver"); //設置連接池驅動
pooldriver.addContent(dsb.getDriver());
newpool.addContent(pooldriver);
Element poolurl=new Element("url");//設置連接池url
poolurl.setText(dsb.getUrl());
newpool.addContent(poolurl);
Element poolusername=new Element("username");//設置連接池用戶名
poolusername.setText(dsb.getUsername());
newpool.addContent(poolusername);
Element poolpassword=new Element("password");//設置連接池密碼
poolpassword.setText(dsb.getPassword());
newpool.addContent(poolpassword);
Element poolmaxconn=new Element("maxconn");//設置連接池最大連接
poolmaxconn.setText(String.valueOf(dsb.getMaxconn()));
newpool.addContent(poolmaxconn);
pools.add(newpool);//將child添加到root
Format format = Format.getPrettyFormat();
format.setIndent("");
format.setEncoding("utf-8");
XMLOutputter outp = new XMLOutputter(format);
fo = new FileOutputStream(rpath);
outp.output(doc, fo);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
}
}
/**
*刪除配置文件
*/
public void delConfigInfo(String path,String name)
{
String rpath=this.getClass().getResource("").getPath().substring(1)+path;
FileInputStream fi = null;
FileOutputStream fo=null;
try
{
fi=new FileInputStream(rpath);//讀取路徑文件
SAXBuilder sb=new SAXBuilder();
Document doc=sb.build(fi);
Element root=doc.getRootElement();
List pools=root.getChildren();
Element pool=null;
Iterator allPool=pools.iterator();
while(allPool.hasNext())
{
pool=(Element)allPool.next();
if(pool.getChild("name").getText().equals(name))
{
pools.remove(pool);
break;
}
}
Format format = Format.getPrettyFormat();
format.setIndent("");
format.setEncoding("utf-8");
XMLOutputter outp = new XMLOutputter(format);
fo = new FileOutputStream(rpath);
outp.output(doc, fo);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try {
fi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String path="ds.config.xml";
pd.readConfigInfo(path);
//pd.delConfigInfo(path, "tj012006");
DSConfigBean dsb=new DSConfigBean();
dsb.setType("oracle");
dsb.setName("yyy004");
dsb.setDriver("org.oracle.jdbc");
dsb.setUrl("jdbc:oracle://localhost");
dsb.setUsername("sa");
dsb.setPassword("");
dsb.setMaxconn(1000);
pd.addConfigInfo(path, dsb);
pd.delConfigInfo(path, "yyy001");
}
--------------------------------------
ds.config.xml 配置文件
--------------------------------------
<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>sql2000</type>
<name>books</name>
<driver>com.microsoft.sqlserver.driver</driver>
<url>jdbc:sqlserver://localhost:1433/books:databasename=books</url>
<username>sa</username>
<password></password>
<maxconn>100</maxconn>
</pool>
</ds-config>
3. 連接池的使用
1。Connection的獲得和釋放
DBConnectionManager connectionMan=DBConnectionManager .getInstance();//得到唯一實例
//得到連接
String name="mysql";//從上下文得到你要訪問的數據庫的名字
Connection con=connectionMan.getConnection(name);
//使用
。。。。。。。
// 使用完畢
connectionMan.freeConnection(name,con);//釋放,但并未斷開連接
2。數據庫連接的動態增加和連接池的動態增加
1。調用xml操作增加類
2。重新實例華連接池管理池類