以前在网上看到一个别人写的连接池,很收启发,但是不记得那位仁兄的名字了,:)今天把它拿出来,改了下,还希望那位仁兄不要“骂”我啊。。嘿嘿。。。
/*
* 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;
}
}
评论