?? dbconnectionmanager.java
字號(hào):
package com.ntsky.pool;
import java.io.*;
import java.sql.*;
import java.util.*;
import com.ntsky.common.*;
/**
* <p>Title: NTsky新聞發(fā)布v1.0正式版</p>
* <p>Description: 數(shù)據(jù)庫(kù)連接池</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: NTsky</p>
* @authory 姚君林
* @version 1.0
*/
public class DBConnectionManager {
static private DBConnectionManager instance; //唯一實(shí)例的引用
static private int clients; //客戶端的連接數(shù)目
private Vector drivers = new Vector();
private Hashtable pools = new Hashtable(); //創(chuàng)建一個(gè)Hashtable對(duì)象
class DBConnectionPool { //定義一個(gè)DBConnectionPool類[如果DBConnectionManager要訪問(wèn)DBConnectionPool必須創(chuàng)建DBConnectionPool的對(duì)象]
private int checkedOut; //判斷是否還有可用的連接
private Vector freeConnections = new Vector();//創(chuàng)建一個(gè)freeConnections的數(shù)組
private int maxConn; //最大連接數(shù)
private String name; //數(shù)據(jù)庫(kù)連接池名
private String user; //訪問(wèn)數(shù)據(jù)庫(kù)用戶名
private String password; //訪問(wèn)數(shù)據(jù)庫(kù)密碼
private String URL; //數(shù)據(jù)庫(kù)地址
private PrintWriter log; //日志
/**
* 配置文件各項(xiàng)參數(shù)
* @param name
* @param url
* @param user
* @param password
* @param maxConn
*/
public DBConnectionPool(String name, String url, String user,
String password, int maxConn) {
/**
*配置文件
*/
this.name = name; //poolname 連接池名
this.URL = url; //地址
this.user = user; //用戶名
this.password = password; //密碼
this.maxConn = maxConn; //最大的連接數(shù)
//寫日志
this.log = new PrintWriter(System.err);
Debug.writeLog("poolname" + this.name); //7、"poolname" + Connection
Debug.writeLog("URL: " + this.URL); //8、jdbc:mysql://127.0.0.1:3306/nt
Debug.writeLog("user: " + this.user); //9、user: skyyjl
Debug.writeLog("password: " + this.password); //10、password: abc
Debug.writeLog("maxConn: " + this.maxConn); //11、maxConn: 100
}
/**
* 把空閑的連接登記到連接池由的freeConnection()方法實(shí)現(xiàn)
* 它的參數(shù)為返回給連接池的連接對(duì)象。該對(duì)象被加入到freeConnections向量的末尾,然后減少已使用連接計(jì)數(shù)。
* 調(diào)用notifyAll()是為了通知其它正在等待可用連接的線程。
* @param Conn
*/
public synchronized void freeConnection(Connection Conn) {
freeConnections.addElement(Conn);
checkedOut--;
notifyAll();
}
/**
* 如連接池中存在可用連接,則直接返回,否則創(chuàng)建新的連接并返回。
* 如果沒(méi)有可用連接且已有連接總數(shù)等于最大限制數(shù),第一個(gè)方法將直接返回null,
* 而第二個(gè)方法將等待直到有可用連接為止
* 所有的可用連接對(duì)象均登記在名為freeConnections的向量(Vector)中。
* 如果向量中有多于一個(gè)的連接,getConnection()總是選取第一個(gè)。
* 由于新的可用連接總是從尾部加入向量,從而使得數(shù)據(jù)庫(kù)連接由于長(zhǎng)時(shí)間閑置而被關(guān)閉的風(fēng)險(xiǎn)減低到最小程度。
*
* @return Connection
*/
public synchronized Connection getConnection() {
Connection con = null;
if (freeConnections.size() > 0) { //獲取向量中第一個(gè)可用連接
con = (Connection) freeConnections.firstElement(); //創(chuàng)建第一個(gè)connection,并用設(shè)置為Connection
freeConnections.removeElementAt(0);
try {
/**
* 第一個(gè)getConnection()在返回可用連接給客戶程序之前,調(diào)用了isClosed()方法驗(yàn)證連接仍舊有效。
* 如果該連接被關(guān)閉或觸發(fā)異常,getConnection()遞歸地調(diào)用自己以嘗試獲取另外的可用連接。
*/
if (con.isClosed()) { //判斷連接是否關(guān)閉
Debug.writeLog("從連接池" + name + "刪除一個(gè)無(wú)效連接");
con = getConnection(); //遞歸調(diào)用自己,嘗試再次獲取可用連接
}
}
catch (SQLException e) {
Debug.writeLog("從連接池" + name + "刪除一個(gè)無(wú)效連接"); // 遞歸調(diào)用自己,嘗試再次獲取可用連接
con = getConnection();
}
}
/**
* 如果在向量freeConnections中不存在任何可用連接,getConnection()方法檢查是否已經(jīng)指定最大連接數(shù)限制。
* 如已經(jīng)指定,則檢查當(dāng)前連接數(shù)是否已經(jīng)到達(dá)極限。此處maxConn為0表示沒(méi)有限制。
* 如果沒(méi)有指定最大連接數(shù)限制或當(dāng)前連接數(shù)小于該值,該方法嘗試創(chuàng)建新的連接。
* 如創(chuàng)建成功,則增加已使用連接的計(jì)數(shù)(checkout)并返回,否則返回空值。
*/
else if (maxConn == 0 || checkedOut < maxConn) {
con = newConnection(); //創(chuàng)建連接(數(shù)量由maxConn決定)
}
if (con != null) { //如果conn(連接數(shù))不為空,判斷就加
checkedOut++;
}
if (con == null) { //如果為空就將con為空寫入日志
Debug.writeLog(
"DBConnectionPool getConnection(), The Returned Con is null");
}
return con; //返回連接
}
/**
* 用一個(gè)以毫秒為單位的時(shí)間參數(shù),該參數(shù)表示客戶程序能夠等待的最長(zhǎng)時(shí)間。
* 建立連接的具體操作仍舊由第一個(gè)getConnection()方法實(shí)現(xiàn)。
* 參見(jiàn)前一個(gè)getConnection()方法.
* @param timeout 以毫秒計(jì)的等待時(shí)間限制
*/
public synchronized Connection getConnection(long timeout) {
long startTime = new java.util.Date().getTime(); //連接的初始時(shí)間
Connection con;
/**
* 在while循環(huán)中嘗試獲得一個(gè)連接。如果失敗,則以給定的時(shí)間值為參數(shù)調(diào)用wait()。
* wait()的返回可能是由于其它線程調(diào)用notify()或notifyAll(),也可能是由于預(yù)定時(shí)間已到。
* 為找出wait()返回的真正原因,程序用當(dāng)前時(shí)間減開(kāi)始時(shí)間(startTime),
* 如差值大于預(yù)定時(shí)間則返回空值,否則再次調(diào)用getConnection()。
*/
while ( (con = getConnection()) == null) {
try {
wait(timeout);
}
catch (InterruptedException e) {
}
if ( (new java.util.Date().getTime() - startTime) >= timeout) { //wait()返回的原因是超時(shí)
return null; //連接超時(shí),釋放掉連接
}
}
return con; //返回連接
}
private void log(String msg) {
log.println(new java.util.Date() + ": " + msg);
}
/**
* 將文本信息與異常寫入日志文件
*/
private void log(Throwable e, String msg) {
log.println(new java.util.Date() + ": " + msg);
e.printStackTrace(log);
}
/**
* 創(chuàng)建新連接由newConnection()方法實(shí)現(xiàn)。
* 創(chuàng)建過(guò)程與是否已經(jīng)指定數(shù)據(jù)庫(kù)帳號(hào)、密碼有關(guān)。
* JDBC的DriverManager類提供多個(gè)getConnection()方法,這些方法要用到JDBC URL與其它一些參數(shù),如用戶帳號(hào)和密碼等。
* DriverManager將使用指定的JDBC URL確定適合于目標(biāo)數(shù)據(jù)庫(kù)的驅(qū)動(dòng)程序及建立連接。
*/
private Connection newConnection() {
Connection con = null;
try {
if (user == null) {
con = DriverManager.getConnection(URL); //保持?jǐn)?shù)據(jù)庫(kù)連接加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序
}
else {
con = DriverManager.getConnection(URL, user, password);
}
Debug.writeLog("連接池" + name + "創(chuàng)建一個(gè)新的連接"); //21、如果有用戶連接就寫入日志說(shuō)明有用戶創(chuàng)建了連接
}
catch (SQLException e) {
Debug.writeLog("無(wú)法創(chuàng)建下列URL的連接: " + URL);
e.printStackTrace(System.out);
return null;
}
if (con == null) {
Debug.writeLog(
"DBConnectionPool newConnection(), The Returned Con is null");
}
return con;
}
/**
* 實(shí)現(xiàn)的release()方法供DBConnectionManager調(diào)用。
* 該方法遍歷freeConnections向量并關(guān)閉所有連接,然后從向量中刪除這些連接。
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -