日期:2014-05-16 浏览次数:20522 次
connectionPool.DBConnectionManager
package connectionPool; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import connectionPool.util.Logger; import connectionPool.util.PropertiesMgr; /** * 连接池的设计思路 * 1、 * 初始化固定数目的连接(空闲连接与活跃连接在同一池中),建立连接的代理类,添加busy与startTime属性以便分发与回收连接 * 另建立守护线程回收失效连接 * 2、 * 维护一空闲连接池,初始为空,需要连接时建立,用完的连接回收进入空闲连接池; * 后续所需连接从空闲连接池获取;activeNum记录活跃连接数目; * 当空闲连接池为空且活跃连接数达到上限时,请求等待,超时即获取连接失败,超时前有连接被释放方可获得连接 * 第二个设计巧妙优势明显,采用第二种方式 * * 数据库连接管理类,单例模式 * 可以管理加载多个数据库驱动,维护多个数据库连接池 * @author shijin * */ public class DBConnectionManager { private static DBConnectionManager dbm = null; //单例模式里的成员变量都相当于是static了? /** * 客户数目 */ private static int clients = 0; /** * 加载的驱动器集合 */ private Set<Driver> drivers = new HashSet<Driver>(); /** * 数据库连接池字典 */ private Hashtable<String,DBConnectionPool> pools = new Hashtable<String,DBConnectionPool>(); private final Logger log = Logger.getInstance(DBConnectionPool.class); private DBConnectionManager() { loadDrivers(); createPools(); } /** * 装载和注册所有的JDBC驱动程序 */ private void loadDrivers() { String str_drivers = PropertiesMgr.getProperty("driver"); for(String str_driver:str_drivers.split("\\s")) { Driver driver = null; try { driver = (Driver)Class.forName(str_driver).newInstance(); DriverManager.registerDriver(driver); log.info("成功加载JDBC驱动:" + str_driver); } catch (InstantiationException e) { log.error("加载JDBC驱动" + str_driver + "时初始化异常,请检查配置文件"); } catch (IllegalAccessException e) { log.info("加载JDBC驱动" + str_driver + "时非法访问,请检查配置文件"); } catch (ClassNotFoundException e) { log.info("未找到JDBC驱动" + str_driver + "请引入相关包"); } catch (SQLException e) { log.info("加载JDBC驱动" + str_driver + "失败,请检查引入包的正确性"); } drivers.add(driver); } } /** * 根据配置文件创建数据库连接池 */ private void createPools() { Enumeration<?> elements = PropertiesMgr.propertiesNames(); while(elements.hasMoreElements()) { String element = (String)elements.nextElement(); if(element.endsWith(".url")) { String poolName = element.substring(0, element.lastIndexOf(".")); String url = PropertiesMgr.getProperty(poolName + ".url"); if(url == null) { log.error("无法连接到数据库" + poolName + "请检查配置文件连接字符串"); continue; } String user = PropertiesMgr.getProperty(poolName + ".user"); String pwd = PropertiesMgr.getProperty(poolName + ".password"); String str_max = PropertiesMgr.getProperty(poolName + ".maxconn", "0"); int maxConn = 0; try{ maxConn = Integer.parseInt(str_max); }catch(NumberFormatException e) { log.error("数据库" + poolName + "最大连接数设置错误,默认设为20"); maxConn = 20; } DBConnectionPool pool = new DBConnectionPool(maxConn,url,poolName,user,pwd); pools.put(poolName, pool); log.info("成功创建数据库连接池" + poolName); } } } /** * 获得单例 * @return DBConnectionManager单例 */ public synchronized static DBConnectionManager getInstance() { if(dbm == null) { dbm = new DBConnectionManager(); } clients++; return dbm; } /** * 从指定连接池中获取可用连接,无等待 * @param poolName 要获取连接的连接池名称 * @return 连接池中的一个可用连接或null */ public Connection getConnection(String poolName) { DBConnectionPool pool = (DBConnectionPool)pools.get(poolName); return pool.getConnection(); } /** * 从指定的连接池获取可用连接,有等待超时 * @param poolName 要获取连接的连接池名称 * @param timeout 获取可用连接的超时时间,