以前在网上看到一个别人写的连接池,很收启发,但是不记得那位仁兄的名字了,:)今天把它拿出来,改了下,还希望那位仁兄不要“骂”我啊。。嘿嘿。。。 /* * Created on 2006-5-24 9:23:26 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates * ===============Version 1.0.0.0====================== */package com; import java.sql.*;import java.util.*;import java.io.*;import com.log.Logger; /** * @author 李国庆 * * Project: Test Package: com ClassName: ConnectionPool */public class ConnectionPool implements TimerListener { // Keep a static ConnectionPool for singleton private static ConnectionPool connectionPool; // Driver name String jdbcDriver; // Connection URL String jdbcConnectionURL; // Minimum size of the pool int connectionPoolSize; // Maximum size of the pool int connectionPoolMax; // Maximum number of uses for a single connection, or -1 for // none int connectionUseCount; // Maximum connection idle time (in minutes) int connectionTimeout; // The connection pool scan interval; int scanInterval; // Additional JDBC properties Properties jdbcProperties; // The Connection pool. This is a vector of ConnectionObject // objects Vector pool; // The maximum number of simultaneous connections as reported // by the JDBC driver int maxConnections = -1; // Our Timer object Timer timer; /** * Empty Constructor */ private ConnectionPool() throws Exception { initialize(); } /** * <p&rt;Initializes the ConnectionPool object using ´database.conf´ under * the WEB-INF/classes as the configuration file * * @return true if the ConnectionPool was initialized properly */ private boolean initialize() throws Exception { return initialize("database.conf"); } /** * <p&rt;Initializes the ConnectionPool object with the specified * configuration file * * @param config * Configuration file name * @return true if the ConnectionPool was initialized properly */ private boolean initialize(String config) throws Exception { boolean rc = loadConfig(config); if (rc) { Logger.println("Creating the pool...."); createPool(); timer = new Timer(this, scanInterval); timer.start(); } return rc; } { } /** * <p&rt;Destroys the pool and it´s contents. Closes any open JDBC * connections and frees all resources */ public void destroy() { try { if (timer != null) { timer.destroy(); timer = null; } if (pool != null) { for (int i = 0; i < pool.size(); i++) { close((ConnectionObject) pool.elementAt(i)); } } pool = null; } catch (Exception ex) { ex.printStackTrace(); } } /** * Create single ConnectionPool if there is not ConnectionPool * * @param none * @return Static ConnectionPool */ public static ConnectionPool getInstance() throws Exception { if (connectionPool == null) { connectionPool = new ConnectionPool(); } return connectionPool; } /** * <p&rt;Gets an available JDBC Connection. Connections will be created if * necessary, up to the maximum number of connections as specified in the * configuration file. * * @return JDBC Connection, or null if the maximum number of connections has * been exceeded */ public synchronized Connection getConnection() { if (pool == null) { return null; } java.sql.Connection con = null; ConnectionObject connectionObject = null; ConnectionObject co = null; int poolSize = pool.size(); for (int i = 0; i < poolSize; i++) { co = (ConnectionObject) pool.elementAt(i); if (co.isAvailable()) { connectionObject = co; break; } } if (connectionObject == null) { if ((connectionPoolMax < 0) || ((connectionPoolMax &rt; 0) && (poolSize < connectionPoolMax))) { int i = addConnection(); if (i &rt;= 0) { connectionObject = (ConnectionObject)pool.elementAt(i); } } else { Logger.println("Maximum number of connections exceeded"); } } if (connectionObject != null) { connectionObject.inUse = true; connectionObject.useCount++; touch(connectionObject); con = connectionObject.con; } return con; } /** * <p&rt;Places the connection back into the connection pool, or closes the * connection if the maximum use count has been reached * * @param Connection * object to close */ public synchronized void close(Connection aCon) { int index = find(aCon); if (index != -1) { ConnectionObject co = (ConnectionObject)pool.elementAt(index); if ((connectionUseCount &rt; 0) && (co.useCount &rt;= connectionUseCount)) { Logger.println("Connection use count exceeded"); removeFromPool(index); } else { touch(co); co.inUse = false; } } } /** * <p&rt;Prints the contents of the connection pool to the standard output * device, test the Pool content */ public void printPool() { System.out.println("--ConnectionPool--"); if (pool != null) { for (int i = 0; i < pool.size(); i++) { ConnectionObject co = (ConnectionObject) pool.elementAt(i); System.out.println("" + i + "=" + co); } } } /** * <p&rt;Removes the ConnectionObject from the pool at the given index * * @param index * Index into the pool vector */ private synchronized void removeFromPool(int index) { if (pool != null) { if (index < pool.size() && (index &rt;= 0)) { ConnectionObject co = (ConnectionObject)pool.elementAt(index); close(co); pool.removeElementAt(index); } } } /** * <p&rt;Closes the connection in the given ConnectionObject * * @param connectObject * ConnectionObject */ private void close(ConnectionObject connectionObject) { if (connectionObject != null) { if (connectionObject.con != null) { try { connectionObject.con.close(); } catch (Exception ex) { } connectionObject.con = null; } } } /** * <p&rt;Loads the given configuration file. All global properties (such as * JDBCDriver) will be read and removed from the properties list. Any * leftover properties will be returned. Returns null if the properties * could not be loaded * * @param name * Configuration file name * @return true if the configuration file was loaded */ private boolean loadConfig(String name) throws Exception{ boolean rc = false; try { jdbcProperties = lc.getConfigProperties(name); if (jdbcProperties == null) rc = false; else { jdbcDriver = consume(jdbcProperties, "DriverName"); jdbcConnectionURL = consume(jdbcProperties, "URL"); connectionPoolSize = consumeInt(jdbcProperties, "ConnectionPoolSize"); connectionPoolMax = consumeInt(jdbcProperties, "ConnectionPoolMax"); connectionUseCount = consumeInt(jdbcProperties, "ConnectionUseCount"); connectionTimeout = consumeInt(jdbcProperties, "ConnectionTimeout"); scanInterval = consumeInt(jdbcProperties, "ScanInterval"); rc = true; } } catch (Exception e) { Logger .println("<Exception&rt;[ConnectionPool]Exception occured while loading config"); // Clean // memory throw new Exception ( "Exception while loading the config"); } return rc; } /** * <p&rt;Consumes the given property and returns the value. * * @param properties * Properties table * @param key * Key of the property to retrieve and remove from the properties * table * @return Value of the property, or null if not found */ private String consume(java.util.Properties p, String key) { String s = null; if ((p != null) && (key != null)) { s = p.getProperty(key); if (s != null) { p.remove(key); } } return s; } /** * <p&rt;Consumes the given property and returns the integer value. * * @param properties * Properties table * @param key * Key of the property to retrieve and remove from the properties * table * @return Value of the property, or -1 if not found */ private int consumeInt(java.util.Properties p, String key) { int n = -1; String value = consume(p, key); if (value != null) { try { n = Integer.parseInt(value); } catch (NumberFormatException ex) { ex.printStackTrace(); } } return n; } /** * <p&rt;Creates the initial connection pool. A timer thread is also created * so that connection timeouts can be handled. * * @return true if the pool was created */ private void createPool() throws Exception { if (jdbcDriver == null) { throw new Exception("JDBCDriver property not found"); } if (jdbcConnectionURL == null) { throw new Exception("JDBCConnectionURL property not found"); } if (connectionPoolSize < 0) { throw new Exception("ConnectionPoolSize property not found"); } if (connectionPoolSize == 0) { throw new Exception("ConnectionPoolSize invalid"); } if (connectionPoolMax < connectionPoolSize) { Logger.println("WARNING - ConnectionPoolMax is invalid and will " + "be ignored"); connectionPoolMax = -1; } if (connectionTimeout < 0) { connectionTimeout = 30; } Logger.println("JDBCDriver = " + jdbcDriver); Logger.println("JDBCConnectionURL = " + jdbcConnectionURL); Logger.println("ConnectionPoolSize = " + connectionPoolSize); Logger.println("ConnectionPoolMax = " + connectionPoolMax); Logger.println("ConnectionUseCount = " + connectionUseCount); Logger.println("ConnectionTimeout = " + connectionTimeout + " seconds"); Logger.println("ScanInterval = " + scanInterval + " seconds"); Logger.println("Registering " + jdbcDriver); java.sql.Driver d = (java.sql.Driver) Class.forName(jdbcDriver) .newInstance(); pool = new java.util.Vector(); fillPool(connectionPoolSize); } /** * <p&rt;Adds a new connection to the pool * * @return Index of the new pool entry, or -1 if an error has occurred */ private int addConnection() { int index = -1; try { int size = pool.size() + 1; fillPool(size); if (size == pool.size()) { index = size - 1; } } catch (Exception ex) { ex.printStackTrace(); } return index; } /** * <p&rt;Brings the pool to the given size * * @size Size of the pool entry */ private synchronized void fillPool(int size) throws Exception { String userID = null; String password = null; if (jdbcProperties != null) { userID = getPropertyIgnoreCase(jdbcProperties, "UserName"); password = getPropertyIgnoreCase(jdbcProperties, "UserPassword"); if (userID == null) userID = "admin"; if (password == null) password = ""; } while (pool.size() < size) { ConnectionObject co = new ConnectionObject(); co.con = DriverManager.getConnection(jdbcConnectionURL, userID, password); if (pool.size() == 0) { java.sql.DatabaseMetaData md = co.con.getMetaData(); maxConnections = md.getMaxConnections(); } if ((maxConnections &rt; 0) && (size &rt; maxConnections)) { Logger.println("WARNING: Size of pool will exceed safe maximum of " +maxConnections); } co.inUse = false; touch(co); pool.addElement(co); } } /** * Gets a the named propery, ignoring case. Returns null if not found * * @param p * The property set * @param name * The property name * @return The value of the propery, or null if not found */ private String getPropertyIgnoreCase(java.util.Properties p, String name) { if ((p == null) || (name == null)) return null; String value = null; java.util.Enumeration enum = p.propertyNames(); while (enum.hasMoreElements()) { String pName = (String) enum.nextElement(); if (pName.equalsIgnoreCase(name)) { value = p.getProperty(pName); break; } } return value; } /** * <p&rt;Find the given connection in the pool * * @return Index into the pool, or -1 if not found */ private int find(java.sql.Connection aCon) { int index = -1; if ((aCon != null) && (pool != null)) { for (int i = 0; i < pool.size(); i++) { ConnectionObject co = (ConnectionObject) pool.elementAt(i); if (co.con == aCon) { index = i; break; } } } return index; } /** * <p&rt;Called by the timer each time a clock cycle expires. * This gives us the opportunity to timeout connections */ public synchronized void TimerEvent(Object object) { if (pool == null) { return; } long now = System.currentTimeMillis(); for (int i = pool.size() - 1; i &rt;= 0; i--) { ConnectionObject co = (ConnectionObject) pool.elementAt(i); if (!co.inUse) { if ((connectionTimeout &rt; 0) && (co.lastAccess +(connectionTimeout * 1000) < now)) { removeFromPool(i); } } } for (int i = pool.size() - 1; i &rt;= 0; i--) { ConnectionObject co = (ConnectionObject)pool.elementAt(i); try { // If the connection is closed, remove it from the pool if (co.con.isClosed()) { Logger.println("Connection closed unexpectedly"); removeFromPool(i); } } catch (Exception ex) { } } try { if (pool != null) { if (pool.size() < connectionPoolSize) { fillPool(connectionPoolSize); } } } catch (Exception ex) { ex.printStackTrace(); } } /** * <p&rt;Sets the last access time for the given ConnectionObject */ private void touch(ConnectionObject co) { if (co != null) { co.lastAccess = System.currentTimeMillis(); } } /** public static void main(String arg[]) throws Exception { ConnectionPool connectionPool = ConnectionPool.getInstance(); System.out.println("Hello World"); } */ } /* * Created on 2006-5-24 9:23:26 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates * ===============Version 1.0.0.0====================== */package com; /** * @author 李国庆 * * Project: Test Package: com ClassName: ConnectionPool */ public class ConnectionObject { // The JDBC Connection public java.sql.Connection con; // true if this connection is currently in use public boolean inUse; // The last time (in milliseconds) that this connection was used public long lastAccess; // The number of times this connection has been used public int useCount; /** * <p&rt;Determine if the connection is available * * @return true if the connection can be used */ public boolean isAvailable() { boolean available = false; try { if (con != null) { if ((!inUse) && (!con.isClosed())) { available = true; } } } catch (Exception ex) { } return available; } /** * <p&rt;Convert the object contents to a String */ public String toString() { return "Connection=" + con + ",inUse=" + inUse + ",lastAccess=" + lastAccess + ",useCount=" + useCount; }}

评论