改写自(Java Servlet Server Programming),实现了Singleton模式。
回复标题:Java中的类的介绍,每个人在日常工作中应该经常能发现一些很有用的类库,可以大大的帮助你提高编码的效率和性能。(-)(1101344)
内容:package com.dreamwork.base;
/**
* Title: DreamWork For XXX
* Description:
* Copyright: Copyright (c) 2001
* Company: DreamWork
* @author James
* @version 1.0
*/
import java.sql.*;
import java.util.*;
import java.io.*;
import com.dreamwork.base.exception.ConfigLoadException;
public class ConnectionPool implements TimerListener
{
// Keep a static ConnectionPool for singleton
private static ConnectionPool connectionPool;
// JDBC Driver name
String jdbcDriver;
// JDBC 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
{
// Load the configuration parameters. Any leftover parameters
// from the configuration file will be considered JDBC
// connection attributes to be used to establish the
// JDBC connections
boolean rc = loadConfig(config);
if (rc)
{
// Properties were loaded; attempt to create our pool
// of connections
Logger.println("Creating the pool....");
createPool();
// Start our timer so we can timeout connections. The
// clock cycle will be 20 seconds
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 {
// Stop our timer thread
if (timer != null)
{
timer.destroy();
timer = null;
}
// Clear our pool
if (pool != null) {
// Loop throught the pool and close each connection
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 there is no pool it must have been destroyed
if (pool == null)
{
return null;
}
java.sql.Connection con = null;
ConnectionObject connectionObject = null;
//temp variable for object exchange
ConnectionObject co = null;
int poolSize = pool.size();
// Get the next available connection
for (int i = 0; i < poolSize; i++)
{
// Get the ConnectionObject from the pool
co = (ConnectionObject) pool.elementAt(i);
// If this is a valid connection and it is not in use,
// grab it
if (co.isAvailable())
{
connectionObject = co;
break;
}
} //end of for
// No more available connections. If we aren't at the
// maximum number of connections, create a new entry
// in the pool
if (connectionObject == null)
{
if ((connectionPoolMax < 0) || ((connectionPoolMax &rt; 0) && (poolSize < connectionPoolMax)))
{
// Add a new connection.
int i = addConnection();
// If a new connection was created, use it
if (i &rt;= 0) {
connectionObject = (ConnectionObject)pool.elementAt(i);
}
}
else {
Logger.println("Maximum number of connections exceeded");
}
}
// If we have a connection, set the last time accessed,
// the use count, and the in use flag
if (connectionObject != null)
{
connectionObject.inUse = true;
connectionObject.useCount++;
touch(connectionObject); //set the last time accessed
con = connectionObject.con;
}
return con; //if maximum number of connections exceeded, return null
}//end of getConnection method
/**
* <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)
{
// Find the connection in the pool
int index = find(aCon);
if (index != -1)
{
ConnectionObject co = (ConnectionObject)pool.elementAt(index);
// If the use count exceeds the max, remove it from
// the pool.
if ((connectionUseCount &rt; 0) && (co.useCount &rt;= connectionUseCount))
{
Logger.println("Connection use count exceeded");
removeFromPool(index);
}
else
{
// Clear the use count and reset the time last used
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)
{
// Make sure the pool and index are valid
if (pool != null)
{
if (index < pool.size() && (index &rt;= 0))
{
// Get the ConnectionObject and close the connection
ConnectionObject co = (ConnectionObject)pool.elementAt(index);
close(co);
// Remove the element from the pool
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
{
// Close the connection
connectionObject.con.close();
}
catch (Exception ex)
{
// Ignore any exceptions during close
}
// Clear the connection object reference
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 com.dreamwork.base.exception.ConfigLoadException
{
Config lc = new Config();
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(ConfigLoadException e){
Logger.println("<Exception&rt;[ConnectionPool]Exception occured while loading config"); // Clean memory
throw new com.dreamwork.base.exception.ConfigLoadException("Exception while loading the config");
}catch(Exception e){
Logger.println("<Exception&rt;[ConnectionPool]Exception occured while loading config"); // Clean memory
throw new com.dreamwork.base.exception.ConfigLoadException("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))
{
// Get the value of the key
s = p.getProperty(key);
// If found, remove it from the properties table
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;
// Get the String value
String value = consume(p, key);
// Got a value; convert to an integer
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
{
// Sanity check our properties
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)
{
// Set the default to 30 minutes
connectionTimeout = 30;
}
// Dump the parameters we are going to use for the pool.
// We don't know what type of servlet environment we will
// be running in - this may go to the console or it
// may be redirected to a log file
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");
// Attempt to create a new instance of the specified
// JDBC driver. Well behaved drivers will register
// themselves with the JDBC DriverManager when they
// are instantiated
Logger.println("Registering " + jdbcDriver);
java.sql.Driver d = (java.sql.Driver)Class.forName(jdbcDriver).newInstance();
// Create the vector for the pool
pool = new java.util.Vector();
// Bring the pool to the minimum size
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
{
// Calculate the new size of the pool
int size = pool.size() + 1;
// Create a new entry
fillPool(size);
// Set the index pointer to the new connection if one
// was created , the order from 0
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 the only properties present are the user id and
// password, get the connection using them instead of
// the properties object
if (jdbcProperties != null)
{
userID = getPropertyIgnoreCase(jdbcProperties, "UserName");
password = getPropertyIgnoreCase(jdbcProperties, "UserPassword");
// If username and userid are null, then we use the default value
if (userID == null) userID = "admin";
if (password == null) password = "";
}
// Loop while we need to create more connections
while (pool.size() < size) {
ConnectionObject co = new ConnectionObject();
// Create the connection
co.con = DriverManager.getConnection(jdbcConnectionURL, userID, password);
// Do some sanity checking on the first connection in
// the pool
if (pool.size() == 0)
{
// Get the maximum number of simultaneous connections
// as reported by the JDBC driver
java.sql.DatabaseMetaData md = co.con.getMetaData();
maxConnections = md.getMaxConnections();
}
// Give a warning if the size of the pool will exceed
// the maximum number of connections allowed by the
// JDBC driver
if ((maxConnections &rt; 0) && (size &rt; maxConnections))
{
Logger.println("WARNING: Size of pool will exceed safe maximum of " +maxConnections);
}
// Clear the in use flag
co.inUse = false;
// Set the last access time
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;
// Get an enumeration of the property names
java.util.Enumeration enum = p.propertyNames();
// Loop through the enum, looking for the given property name
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;
// Find the matching Connection in the pool
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)
{
// No pool means no work
if (pool == null)
{
return;
}
// Get the current time in milliseconds
long now = System.currentTimeMillis();
// Check for any expired connections and remove them
for (int i = pool.size() - 1; i &rt;= 0; i--)
{
ConnectionObject co = (ConnectionObject) pool.elementAt(i);
// If the connection is not in use and it has not been
// used recently, remove it
if (!co.inUse)
{
if ((connectionTimeout &rt; 0) && (co.lastAccess +(connectionTimeout * 1000) < now))
{
removeFromPool(i);
}
}
}
// Remove any connections that are no longer open
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) { }
}
// Now ensure that the pool is still at it's minimum size
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");
}
*/
} //End of class ConnectionPool.java
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
{
// To be available, the connection cannot be in use
// and must be open
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;
}
}//End of ConntectionObject.java
posted on 2007-07-18 13:57
蛮哥♂枫 阅读(326)
评论(0) 编辑 收藏 所属分类:
Java