正文

一个不错的连接池2006-05-24 09:56:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/ggbm/14767.html

分享到:

            以前在网上看到一个别人写的连接池,很收启发,但是不记得那位仁兄的名字了,:)今天把它拿出来,改了下,还希望那位仁兄不要“骂”我啊。。嘿嘿。。。
    

/*
 * 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;
    }
}

阅读(2585) | 评论(2)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册