📄 dbconnectionmanager.java
字号:
public synchronized void release() {
Enumeration allConnections = freeConnections.elements();
while (allConnections.hasMoreElements()) { //freeConnections对象存在
Connection con = (Connection) allConnections.nextElement(); //取出所有的数组
try {
con.close(); //尝试关闭
Debug.writeLog("关闭连接池" + name + "中的一个连接");
}
catch (SQLException e) {
Debug.writeLog("无法关闭连接池" + name + "中的连接");
e.printStackTrace(System.out);
}
}
freeConnections.removeAllElements(); //清空
}
}
/**
* *****************************************************************
* 建构函数私有以防止其它对象创建本类实例
* 其它对象能够调用其静态方法(也称为类方法)获得该唯一实例的引用
* DBConnectionManager类的建构函数是私有的,这是为了避免其它对象创建该类的实例。
*/
private DBConnectionManager() {
init();
}
/**
*
* @param props 连接池属性
*/
private void createPools(Properties props) {
Enumeration propNames = props.propertyNames(); //创建枚举对象----该对象可以想象为一个元素系列,逐次调用其nextElement()方法将顺序返回各元素
while (propNames.hasMoreElements()) { //如果有枚举对象存在
String name = (String) propNames.nextElement(); //取出值格式为字符串
Debug.writeLog("createPools(Properties), name is: " + name); //3、logPath 将路径名写入日志
/**
* 在其中搜索名字以“.url”结尾的属性
* 对于每一个符合条件的属性,先提取其连接池名字部分,进而读取所有属于该连接池的属性
*/
if (name.endsWith(".url")) {
Debug.writeLog("createPools(Properties), name end with url"); //5
String poolName = name.substring(0, name.lastIndexOf(".")); //取出“.”之前的字符串(连接池的名字)
String url = props.getProperty(poolName + ".url"); //4、Connection.url 取得URL
Debug.writeLog("createPools(Properties), url is " + url); //6、jdbc:mysql://127.0.0.1:3306/nt 写入数据库的url"jdbc:mysql://127.0.0.1:3306/数据名"
if (url == null) { //如果URL为空,写入日志显示没有找到指定的URL
Debug.writeLog("没有为连接池" + poolName + "指定URL");
continue; //跳出本次循环
}
String user = props.getProperty(poolName + ".user"); //用户名
String password = props.getProperty(poolName + ".password"); //密码
String maxconn = props.getProperty(poolName + ".maxconn", "0"); //最大连接数
int max; //定义一个整形变量
try {
max = Integer.valueOf(maxconn).intValue(); //取得最大连接数的值
}
catch (NumberFormatException e) {
Debug.writeLog("错误的最大连接数限制: " + maxconn + " .连接池: " +
poolName);
max = 0;
}
//创建连接池对象并把它保存在实例变量pools中
DBConnectionPool pool = new DBConnectionPool(poolName, url, user, password, max);
//散列表(Hashtable类 )pools实现连接池名字到连接池对象之间的映射,此处以连接池名字为键,连接池对象为值。
pools.put(poolName, pool);
Debug.writeLog("成功创建连接池" + poolName); //12、成功创建连接池Connection
}
}
}
/**
* 将连接对象返回给由名字指定的连接池
* @param name 在属性文件中定义的连接池名字
* @param con 连接对象
*/
public void freeConnection(String name, Connection con) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
pool.freeConnection(con);
}
}
/**
* 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数
* 限制,则创建并返回新连接
* @param name 在属性文件中定义的连接池名字
* @return Connection 可用连接或null
*/
public Connection getConnection(String name) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
Debug.writeLog(
"DBConnectionManager getConnection(String) ! pool is not null !"); //20
return pool.getConnection();
}
return null;
}
/**
* 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,
* 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.
* @param name 连接池名字
* @param time 以毫秒计的等待时间
* @return Connection 可用连接或null
*/
public Connection getConnection(String name, long time) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection(time);
}
return null;
}
/**
* 其引用就一直保存在静态变量instance中
* 每次调用getInstance()都增加一个DBConnectionManager的客户程序计数。
* 该计数代表引用DBConnectionManager唯一实例的客户程序总数,它将被用于控制连接池的关闭操作。
* @return 返回唯一实例.如果是第一次调用此方法,则创建实例
*/
public static synchronized DBConnectionManager getInstance() {
if (instance == null) {
instance = new DBConnectionManager();
}
clients++; //对客户端的访问计数
return instance;
}
/**
* 读取属性完成初始化
*/
private void init() {
//[配置文件路径(ISiteEnvironment.ConfigFile)]调用EnvironmentConfig的getProperties()方法
Properties dbProps = EnvironmentConfig.getInstance().getProperties(
ISiteEnvironment.ConfigFile);
loadDrivers(dbProps); //装载驱动
createPools(dbProps); //调用私有方法createPools()创建连接池对象
}
/**
* 装载和注册所有JDBC驱动程序
* 该方法先用StringTokenizer将drivers属性值分割为对应于驱动程序名称的字符串
*
* @param props 属性
*/
private void loadDrivers(Properties props) {
String driverClasses = props.getProperty("drivers");
StringTokenizer st = new StringTokenizer(driverClasses);
while (st.hasMoreElements()) {
String driverClassName = st.nextToken().trim(); //取得驱动程序org.gjt.mm.mysql.Driver
try {
Driver driver = (Driver) Class.forName(driverClassName).
newInstance();
DriverManager.registerDriver(driver);
Debug.writeLog("Load Driver Success !"); //1、加载驱动成功
drivers.addElement(driver);
Debug.writeLog("成功注册JDBC驱动程序" + driverClassName); //2、加载JDBC驱动程序org.gjt.mm.mysql.Driver
}
catch (Exception e) {
Debug.writeLog("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);
}
}
}
/**
* 客户程序在关闭时调用release()可以递减该计数。
* 当最后一个客户程序调用release(),递减后的引用计数为0,就可以调用各个连接池的release()方法关闭所有连接了。
* 关闭所有连接,撤销驱动程序的注册
*/
public synchronized void release() { //等待直到最后一个客户程序调用
if (--clients != 0) {
return;
}
Enumeration allPools = pools.elements();
while (allPools.hasMoreElements()) {
DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();
pool.release();
}
Enumeration allDrivers = drivers.elements();
while (allDrivers.hasMoreElements()) {
Driver driver = (Driver) allDrivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
Debug.writeLog("撤销JDBC驱动程序 " + driver.getClass().getName() + "的注册");
}
catch (SQLException e) {
Debug.writeLog("无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
e.printStackTrace(System.out);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -