﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-Nick.Chang Blog</title><link>http://www.blogjava.net/kaola8646/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 21 Jun 2026 10:12:40 GMT</lastBuildDate><pubDate>Sun, 21 Jun 2026 10:12:40 GMT</pubDate><ttl>60</ttl><item><title>完整连接池</title><link>http://www.blogjava.net/kaola8646/articles/237421.html</link><dc:creator>Nick.Chang</dc:creator><author>Nick.Chang</author><pubDate>Wed, 29 Oct 2008 09:27:00 GMT</pubDate><guid>http://www.blogjava.net/kaola8646/articles/237421.html</guid><wfw:comment>http://www.blogjava.net/kaola8646/comments/237421.html</wfw:comment><comments>http://www.blogjava.net/kaola8646/articles/237421.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kaola8646/comments/commentRss/237421.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kaola8646/services/trackbacks/237421.html</trackback:ping><description><![CDATA[<span style="font-family: Times New Roman"><span style="font-family: 宋体">
<h4 style="font-family: 宋体">/**<br />
&nbsp;* 完整连接池<br />
&nbsp;*/<br />
import java.io.*;<br />
import java.sql.*;<br />
import java.util.*;<br />
import java.util.Date;</h4>
<h4>/**<br />
&nbsp;* 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接<br />
&nbsp;* 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例.<br />
&nbsp;*/</h4>
<h4>public class DBConnectionManager {<br />
&nbsp;static private DBConnectionManager instance; // 唯一实例</h4>
<h4>&nbsp;static private int clients;</h4>
<h4>&nbsp;private Vector drivers = new Vector();</h4>
<h4>&nbsp;private PrintWriter log;</h4>
<h4>&nbsp;private Hashtable pools = new Hashtable();</h4>
<h4>&nbsp;/**<br />
&nbsp; * 返回唯一实例.如果是第一次调用此方法,则创建实例<br />
&nbsp; *<br />
&nbsp; * @return DBConnectionManager 唯一实例<br />
&nbsp; **/<br />
&nbsp;static synchronized public DBConnectionManager getInstance() {<br />
&nbsp;&nbsp;if (instance == null) {<br />
&nbsp;&nbsp;&nbsp;instance = new DBConnectionManager();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;clients++;<br />
&nbsp;&nbsp;return instance;<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 建构函数私有以防止其它对象创建本类实例<br />
&nbsp; */<br />
&nbsp;private DBConnectionManager() {<br />
&nbsp;&nbsp;init();<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 将连接对象返回给由名字指定的连接池<br />
&nbsp; *<br />
&nbsp; * @param name 在属性文件中定义的连接池名字<br />
&nbsp; * @param con 连接对象<br />
&nbsp; **/<br />
&nbsp;public void freeConnection(String name, Connection con) {<br />
&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br />
&nbsp;&nbsp;if (pool != null) {<br />
&nbsp;&nbsp;&nbsp;pool.freeConnection(con);<br />
&nbsp;&nbsp;}<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数<br />
&nbsp; * 限制,则创建并返回新连接<br />
&nbsp; *<br />
&nbsp; * @param name 在属性文件中定义的连接池名字<br />
&nbsp; * @return Connection 可用连接或null<br />
&nbsp; */<br />
&nbsp;public Connection getConnection(String name) {<br />
&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br />
&nbsp;&nbsp;if (pool != null) {<br />
&nbsp;&nbsp;&nbsp;return pool.getConnection();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return null;<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,<br />
&nbsp; * 则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接.<br />
&nbsp; *<br />
&nbsp; * @param name 连接池名字<br />
&nbsp; * @param time 以毫秒计的等待时间<br />
&nbsp; * @return Connection 可用连接或null<br />
&nbsp; */<br />
&nbsp;public Connection getConnection(String name, long time) {<br />
&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) pools.get(name);<br />
&nbsp;&nbsp;if (pool != null) {<br />
&nbsp;&nbsp;&nbsp;return pool.getConnection(time);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return null;<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 关闭所有连接,撤销驱动程序的注册<br />
&nbsp; */<br />
&nbsp;public synchronized void release() {<br />
&nbsp;&nbsp;// 等待直到最后一个客户程序调用<br />
&nbsp;&nbsp;if (--clients != 0) {<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}</h4>
<h4>&nbsp;&nbsp;Enumeration allPools = pools.elements();<br />
&nbsp;&nbsp;while (allPools.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;DBConnectionPool pool = (DBConnectionPool) allPools.nextElement();<br />
&nbsp;&nbsp;&nbsp;pool.release();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;Enumeration allDrivers = drivers.elements();<br />
&nbsp;&nbsp;while (allDrivers.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;Driver driver = (Driver) allDrivers.nextElement();<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;DriverManager.deregisterDriver(driver);<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("撤销JDBC驱动程序 " + driver.getClass().getName() + "的注册");<br />
&nbsp;&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 根据指定属性创建连接池实例.<br />
&nbsp; *<br />
&nbsp; * @param props 连接池属性<br />
&nbsp; */<br />
&nbsp;private void createPools(Properties props) {<br />
&nbsp;&nbsp;Enumeration propNames = props.propertyNames();<br />
&nbsp;&nbsp;while (propNames.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;String name = (String) propNames.nextElement();<br />
&nbsp;&nbsp;&nbsp;if (name.endsWith(".url")) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;String poolName = name.substring(0, name.lastIndexOf("."));<br />
&nbsp;&nbsp;&nbsp;&nbsp;String url = props.getProperty(poolName + ".url");<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (url == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("没有为连接池" + poolName + "指定URL");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;String user = props.getProperty(poolName + ".user");<br />
&nbsp;&nbsp;&nbsp;&nbsp;String password = props.getProperty(poolName + ".password");<br />
&nbsp;&nbsp;&nbsp;&nbsp;String maxconn = props.getProperty(poolName + ".maxconn", "0");<br />
&nbsp;&nbsp;&nbsp;&nbsp;int max;<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = Integer.valueOf(maxconn).intValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (NumberFormatException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("错误的最大连接数限制: " + maxconn + " .连接池: " + poolName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;DBConnectionPool pool = new DBConnectionPool(poolName, url,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user, password, max);<br />
&nbsp;&nbsp;&nbsp;&nbsp;pools.put(poolName, pool);<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("成功创建连接池" + poolName);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 读取属性完成初始化<br />
&nbsp; */<br />
&nbsp;private void init() {<br />
&nbsp;&nbsp;InputStream is = getClass().getResourceAsStream("/db.properties");<br />
&nbsp;&nbsp;Properties dbProps = new Properties();<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;dbProps.load(is);<br />
&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;System.err.println("不能读取属性文件. "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ "请确保db.properties在CLASSPATH指定的路径中");<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;String logFile = dbProps.getProperty("logfile",<br />
&nbsp;&nbsp;&nbsp;&nbsp;"DBConnectionManager.log");<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;log = new PrintWriter(new FileWriter(logFile, true), true);<br />
&nbsp;&nbsp;} catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;System.err.println("无法打开日志文件: " + logFile);<br />
&nbsp;&nbsp;&nbsp;log = new PrintWriter(System.err);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;loadDrivers(dbProps);<br />
&nbsp;&nbsp;createPools(dbProps);<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 装载和注册所有JDBC驱动程序<br />
&nbsp; *<br />
&nbsp; * @param props 属性<br />
&nbsp; */<br />
&nbsp;private void loadDrivers(Properties props) {<br />
&nbsp;&nbsp;String driverClasses = props.getProperty("drivers");<br />
&nbsp;&nbsp;StringTokenizer st = new StringTokenizer(driverClasses);<br />
&nbsp;&nbsp;while (st.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;String driverClassName = st.nextToken().trim();<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Driver driver = (Driver) Class.forName(driverClassName)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.newInstance();<br />
&nbsp;&nbsp;&nbsp;&nbsp;DriverManager.registerDriver(driver);<br />
&nbsp;&nbsp;&nbsp;&nbsp;drivers.addElement(driver);<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("成功注册JDBC驱动程序" + driverClassName);<br />
&nbsp;&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("无法注册JDBC驱动程序: " + driverClassName + ", 错误: " + e);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 将文本信息写入日志文件<br />
&nbsp; */<br />
&nbsp;private void log(String msg) {<br />
&nbsp;&nbsp;log.println(new Date() + ": " + msg);<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 将文本信息与异常写入日志文件<br />
&nbsp; */<br />
&nbsp;private void log(Throwable e, String msg) {<br />
&nbsp;&nbsp;log.println(new Date() + ": " + msg);<br />
&nbsp;&nbsp;e.printStackTrace(log);<br />
&nbsp;}</h4>
<h4>&nbsp;/**<br />
&nbsp; * 此内部类定义了一个连接池.它能够根据要求创建新连接,直到预定的最<br />
&nbsp; * 大连接数为止.在返回连接给客户程序之前,它能够验证连接的有效性.<br />
&nbsp; */<br />
&nbsp;class DBConnectionPool {<br />
&nbsp;&nbsp;private int checkedOut;</h4>
<h4>&nbsp;&nbsp;private Vector freeConnections = new Vector();</h4>
<h4>&nbsp;&nbsp;private int maxConn;</h4>
<h4>&nbsp;&nbsp;private String name;</h4>
<h4>&nbsp;&nbsp;private String password;</h4>
<h4>&nbsp;&nbsp;private String URL;</h4>
<h4>&nbsp;&nbsp;private String user;</h4>
<h4>&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 创建新的连接池<br />
&nbsp;&nbsp; *<br />
&nbsp;&nbsp; * @param name 连接池名字<br />
&nbsp;&nbsp; * @param URL 数据库的JDBC URL<br />
&nbsp;&nbsp; * @param user 数据库帐号,或 null<br />
&nbsp;&nbsp; * @param password 密码,或 null<br />
&nbsp;&nbsp; * @param maxConn 此连接池允许建立的最大连接数<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public DBConnectionPool(String name, String URL, String user,<br />
&nbsp;&nbsp;&nbsp;&nbsp;String password, int maxConn) {<br />
&nbsp;&nbsp;&nbsp;this.name = name;<br />
&nbsp;&nbsp;&nbsp;this.URL = URL;<br />
&nbsp;&nbsp;&nbsp;this.user = user;<br />
&nbsp;&nbsp;&nbsp;this.password = password;<br />
&nbsp;&nbsp;&nbsp;this.maxConn = maxConn;<br />
&nbsp;&nbsp;}</h4>
<h4>&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 将不再使用的连接返回给连接池<br />
&nbsp;&nbsp; *<br />
&nbsp;&nbsp; * @param con 客户程序释放的连接<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized void freeConnection(Connection con) {<br />
&nbsp;&nbsp;&nbsp;// 将指定连接加入到向量末尾<br />
&nbsp;&nbsp;&nbsp;freeConnections.addElement(con);<br />
&nbsp;&nbsp;&nbsp;checkedOut--;<br />
&nbsp;&nbsp;&nbsp;notifyAll();<br />
&nbsp;&nbsp;}</h4>
<h4>&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接<br />
&nbsp;&nbsp; * 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,<br />
&nbsp;&nbsp; * 然后递归调用自己以尝试新的可用连接.<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized Connection getConnection() {<br />
&nbsp;&nbsp;&nbsp;Connection con = null;<br />
&nbsp;&nbsp;&nbsp;if (freeConnections.size() &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 获取向量中第一个可用连接<br />
&nbsp;&nbsp;&nbsp;&nbsp;con = (Connection) freeConnections.firstElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;freeConnections.removeElementAt(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (con.isClosed()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("从连接池" + name + "删除一个无效连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 递归调用自己,尝试再次获取可用连接<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con = getConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("从连接池" + name + "删除一个无效连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 递归调用自己,尝试再次获取可用连接<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con = getConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;} else if (maxConn == 0 || checkedOut &lt; maxConn) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;con = newConnection();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;if (con != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;checkedOut++;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return con;<br />
&nbsp;&nbsp;}</h4>
<h4>&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 从连接池获取可用连接.可以指定客户程序能够等待的最长时间<br />
&nbsp;&nbsp; * 参见前一个getConnection()方法.<br />
&nbsp;&nbsp; *<br />
&nbsp;&nbsp; * @param timeout 以毫秒计的等待时间限制<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized Connection getConnection(long timeout) {<br />
&nbsp;&nbsp;&nbsp;long startTime = new Date().getTime();<br />
&nbsp;&nbsp;&nbsp;Connection con;<br />
&nbsp;&nbsp;&nbsp;while ((con = getConnection()) == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait(timeout);<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (InterruptedException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;if ((new Date().getTime() - startTime) &gt;= timeout) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// wait()返回的原因是超时<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return con;<br />
&nbsp;&nbsp;}</h4>
<h4>&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 关闭所有连接<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;public synchronized void release() {<br />
&nbsp;&nbsp;&nbsp;Enumeration allConnections = freeConnections.elements();<br />
&nbsp;&nbsp;&nbsp;while (allConnections.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Connection con = (Connection) allConnections.nextElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log("关闭连接池" + name + "中的一个连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;} catch (SQLException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log(e, "无法关闭连接池" + name + "中的连接");<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;freeConnections.removeAllElements();<br />
&nbsp;&nbsp;}</h4>
<h4>&nbsp;&nbsp;/**<br />
&nbsp;&nbsp; * 创建新的连接<br />
&nbsp;&nbsp; /**/<br />
&nbsp;&nbsp;private Connection newConnection() {<br />
&nbsp;&nbsp;&nbsp;Connection con = null;<br />
&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (user == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con = DriverManager.getConnection(URL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;log("无法取得新连接");<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return con;<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
</h4>
</span></span>
<img src ="http://www.blogjava.net/kaola8646/aggbug/237421.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kaola8646/" target="_blank">Nick.Chang</a> 2008-10-29 17:27 <a href="http://www.blogjava.net/kaola8646/articles/237421.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>