package org.toolkit.pool;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import org.toolkit.wrapper.LogWrapper;
import org.toolkit.wrapper.PropertyWrapper;
public class DBConnectionPool implements Runnable{
private String dbDiv = ""; // 数据库驱动
private String dbUrl = ""; // 数据 URL
private String dbUser = ""; // 数据库用户名
private String dbPassword = ""; // 数据库用户密码
private String testTable = ""; // 测试连接是否可用的测试表名,默认没有测试表
private int initialConnections = 10; // 连接池的初始大小
private int incrementalConnections = 5;// 连接池自动增加的大小
private int maxConnections = 50; // 连接池最大的大小
private long checkRelaseConnectionTime = 4 * 60 * 60 * 1000; //连接池中释放数据库连接时间 4 *60 * 60 * 1000
private boolean isRunning = true; //线程运行标识
private Vector<PooledConnection> pooledConnectionVector = null; // 存放连接池中数据库连接的向量 , 初始时为 null 存放的对象为 PooledConnection 型
LogWrapper logWrapper = LogWrapper.getInstance();//日志管理对像
private static DBConnectionPool dbConnectionPool = null; //本类单例对像
/**
* 默认构造函数
*
*/
private DBConnectionPool() {
this.dbDiv = new String((String)PropertyWrapper.getInstance().getPropertyFromFile("dbDiv"));
this.dbUrl = new String((String)PropertyWrapper.getInstance().getPropertyFromFile("dbUrl"));
this.dbUser = new String((String)PropertyWrapper.getInstance().getPropertyFromFile("dbUser"));
this.dbPassword = new String((String)PropertyWrapper.getInstance().getPropertyFromFile("dbPassword"));
this.testTable = new String((String)PropertyWrapper.getInstance().getPropertyFromFile("testTable"));
this.initialConnections = Integer.parseInt(new String((String)PropertyWrapper.getInstance().getPropertyFromFile("initialConnections")));
this.incrementalConnections = Integer.parseInt(new String((String)PropertyWrapper.getInstance().getPropertyFromFile("incrementalConnections")));
this.maxConnections = Integer.parseInt(new String((String)PropertyWrapper.getInstance().getPropertyFromFile("maxConnections")));
this.checkRelaseConnectionTime = Long.parseLong(new String((String)PropertyWrapper.getInstance().getPropertyFromFile("checkRelaseConnectionTime"))) * 1000;
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbDiv = "+dbDiv+"}");//记录日志
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbUrl = "+dbUrl+"}");//记录日志
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbUser = "+dbUser+"}");//记录日志
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbPassword = "+dbPassword+"}");//记录日志
try {
createConnectionPool();
} catch (Exception e) {
e.printStackTrace();
}
}
//静态工厂方法
public synchronized static DBConnectionPool getInstance() {
if (dbConnectionPool == null) {
dbConnectionPool = new DBConnectionPool();
}
return dbConnectionPool;
}
/**
* 构造函数
*
* @param jdbcDriver String JDBC 驱动类串
* @param dbUrl String 数据库 URL
* @param dbUserName String 连接数据库用户名
* @param dbPassword String 连接数据库用户的密码
*
*/
public DBConnectionPool(String dbDiv, String dbUrl, String dbUser, String dbPassword) {
this.dbDiv = dbDiv;
this.dbUrl = dbUrl;
this.dbUser = dbUser;
this.dbPassword = dbPassword;
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbDiv = "+dbDiv+"}");//记录日志
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbUrl = "+dbUrl+"}");//记录日志
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbUser = "+dbUser+"}");//记录日志
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"dbPassword = "+dbPassword+"}");//记录日志
try {
createConnectionPool();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* =======================连接池操作=======================
*/
/**
*
* 创建一个数据库连接池,连接池中的可用连接的数量采用类成员
* initialConnections 中设置的值
*/
public synchronized void createConnectionPool() throws Exception{
// 确保连接池没有创建
// 如果连接池己经创建了,保存连接的向量 connections 不会为空
if (pooledConnectionVector != null) {
return; // 如果己经创建,则返回
}
// 实例化 JDBC Driver 中指定的驱动类实例
Driver driver;
driver = (Driver) (Class.forName(this.dbDiv).newInstance());
DriverManager.registerDriver(driver); // 注册 JDBC 驱动程序
// 创建保存连接的向量 , 初始时有 0 个元素
pooledConnectionVector = new Vector<PooledConnection>();
// 根据 initialConnections 中设置的值,创建连接。
initConnectionToPool(this.initialConnections);
if (pooledConnectionVector == null || pooledConnectionVector.size() <=0 ) {
logWrapper.Warn("{"+this.logWrapper.getTraceInfo()+"; msg: "+"数据库连接池创建失败!"+"}");//记录日志
} else{
logWrapper.Normal("{"+this.logWrapper.getTraceInfo()+"; msg: "+"数据库连接池创建成功!"+"}");//记录日志
new Thread(this).start();//启动本类线程
}
}
/**
* 刷新连接池中所有的连接对象
*
*/
public synchronized void refreshConnectionPool() throws SQLException {
// 确保连接池己创新存在
if (pooledConnectionVector == null) {
// System.out.println(" 连接池不存在,无法刷新 !");
logWrapper.Warn("{"+this.logWrapper.getTraceInfo()+"; msg: "+"连接池不存在,无法刷新!"+"}");//记录日志
return;
}
PooledConnection pConn = null;
Enumeration<PooledConnection> enumerate = pooledConnectionVector.elements();
while (enumerate.hasMoreElements()) {
// 获得一个连接对象
pConn = (PooledConnection) enumerate.nextElement();
// 如果对象忙则等 5 秒 ,5 秒后直接刷新
if (pConn.isBusy()) {
wait(5000); // 等 5 秒
}
// 关闭此连接,用一个新的连接代替它。
try {
pConn.getConnection().close();
} catch (SQLException sqle) {
logWrapper.Warn("{"+this