发信人: huanghwh(五云人) 
整理人: zjxyz(2003-02-23 14:59:14), 站内信件
 | 
 
 
【 在 liuzhenai 的大作中提到:】
 :
 :连接池,可以提高JSP程序的效率,jsp使用连接池是很有必要的,但是兄弟我对连接池还知之甚少,请哪位老兄用精简、通俗的语言给我补一课,谢谢!!
 :
 :1、从本质上讲,连接池到底有什么作用(主要结合jsp,mssql/oracle)?
 :2、从形式上讲,连接池的使用,需要掌哪几个类?(最好举个例,这样会清楚很多)
 :
 :......
 part two
 
    /**
     * <p>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;
 
       // Get our class loader
       ClassLoader cl = getClass().getClassLoader();
 
       // Attempt to open an input stream to the configuration file.
       // The configuration file is considered to be a system
       // resource.
       java.io.InputStream in;
 
       if (cl != null) {
         in = cl.getResourceAsStream(name);
       }
       else {
         in = ClassLoader.getSystemResourceAsStream(name);
       }
 
       if (in == null) { //use normal FileInpustream
         in = new FileInputStream(name);
       }
 
       // If the input stream is null, then the configuration file
       // was not found
       if(in == null)
         throw new Exception("ConnectionPool configuration file '" +
                            name + "' not found");
       else {
         try {
           m_JDBCProperties = new java.util.Properties();
           java.util.Properties allProperties = new java.util.Properties();
           allProperties.load(in);
           // Load the configuration file into the properties table
           //m_JDBCProperties.load(in);
 
           //fill m_JDBCProperties
           m_JDBCProperties.put("JDBCDriver", allProperties.getProperty("JDBCDriver"));
           m_JDBCProperties.put("JDBCConnectionURL", allProperties.getProperty("JDBCConnectionURL"));
           m_JDBCProperties.put("ConnectionPoolSize", allProperties.getProperty("ConnectionPoolSize"));
           m_JDBCProperties.put("ConnectionPoolMax", allProperties.getProperty("ConnectionPoolMax"));
           m_JDBCProperties.put("ConnectionTimeout", allProperties.getProperty("ConnectionTimeout"));
           m_JDBCProperties.put("ConnectionUseCount", allProperties.getProperty("ConnectionUseCount"));
           m_JDBCProperties.put("User", allProperties.getProperty("User"));
           m_JDBCProperties.put("Password", allProperties.getProperty("Password"));
           allProperties.clear();
 
           // Got the properties. Pull out the properties that we
           // are interested in
           m_JDBCDriver = consume(m_JDBCProperties, "JDBCDriver");
           m_JDBCConnectionURL = consume(m_JDBCProperties,
                                         "JDBCConnectionURL");
           m_ConnectionPoolSize = consumeInt(m_JDBCProperties,
                                             "ConnectionPoolSize");
           m_ConnectionPoolMax = consumeInt(m_JDBCProperties,
                                            "ConnectionPoolMax");
           m_ConnectionTimeout = consumeInt(m_JDBCProperties,
                                            "ConnectionTimeout");
           m_ConnectionUseCount = consumeInt(m_JDBCProperties,
                                             "ConnectionUseCount");
           rc = true;
         }
         finally {
           // Always close the input stream
           if (in != null) {
             try {
               in.close();
             }
             catch (Exception ex) {
             }
           }
         }
       }
       return rc;
     }
 
   /**
     * <p>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>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 (Exception ex) {
         }
       }
       return n;
     }
 
   /**
     * <p>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 (m_JDBCDriver == null) {
         throw new Exception("JDBCDriver property not found");
       }
       if (m_JDBCConnectionURL == null) {
         throw new Exception("JDBCConnectionURL property not found");
       }
       if (m_ConnectionPoolSize < 0) {
         throw new Exception("ConnectionPoolSize property not found");
       }
       if (m_ConnectionPoolSize == 0) {
         throw new Exception("ConnectionPoolSize invalid");
       }
       if (m_ConnectionPoolMax < m_ConnectionPoolSize) {
         trace("WARNING - ConnectionPoolMax is invalid and will " +
               "be ignored");
         m_ConnectionPoolMax = -1;
       }
       if (m_ConnectionTimeout < 0) {
         // Set the default to 30 minutes
         m_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
       //trace("JDBCDriver = " + m_JDBCDriver);
       //trace("JDBCConnectionURL = " + m_JDBCConnectionURL);
       //trace("ConnectionPoolSize = " + m_ConnectionPoolSize);
       //trace("ConnectionPoolMax = " + m_ConnectionPoolMax);
       //trace("ConnectionUseCount = " + m_ConnectionUseCount);
       //trace("ConnectionTimeout = " + m_ConnectionTimeout +
       //      " seconds");
 
       // Also dump any additional JDBC properties
       java.util.Enumeration enum = m_JDBCProperties.keys();
       while (enum.hasMoreElements()) {
         String key = (String) enum.nextElement();
         String value = m_JDBCProperties.getProperty(key);
         //trace("(JDBC Property) " + key + " = " + value);
       }
 
       // 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
       //trace("Registering " + m_JDBCDriver);
       java.sql.Driver d = (java.sql.Driver)
         Class.forName(m_JDBCDriver).newInstance();
 
       // Create the vector for the pool
       m_pool = new java.util.Vector();
 
       // Bring the pool to the minimum size
       fillPool(m_ConnectionPoolSize);
     }
 
   /**
     * <p>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 = m_pool.size() + 1;
 
         // Create a new entry
         fillPool(size);
 
         // Set the index pointer to the new connection if one
         // was created
         if (size == m_pool.size()) {
           index = size - 1;
         }
       }
       catch (Exception ex) {
         ex.printStackTrace();
       }
       return index;
     }
 
   /**
     * <p>Brings the pool to the given size
     */
   private synchronized void fillPool(int size) throws Exception
     {
       boolean useProperties = true;
       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 (m_JDBCProperties != null) {
 
         // Make sure there are only 2 properties, and they are
         // the user id and password
         if (m_JDBCProperties.size() == 2) {
           userID =
             getPropertyIgnoreCase(m_JDBCProperties, "user");
           password =
             getPropertyIgnoreCase(m_JDBCProperties, "password");
 
           // If all we've got is a user id and password then
           // don't use the properties
           if ((userID != null) && (password != null)) {
             useProperties = false;
           }
         }
 
       }
 
       // Loop while we need to create more connections
       while (m_pool.size() < size) {
 
         ConnectionObject co = new ConnectionObject();
 
         // Create the connection
         if (useProperties) {
           co.con = DriverManager.getConnection(m_JDBCConnectionURL,
                                               m_JDBCProperties);
         }
         else {
           co.con = DriverManager.getConnection(m_JDBCConnectionURL,
                                                userID, password);
         }
 
         // Do some sanity checking on the first connection in
         // the pool
         if (m_pool.size() == 0) {
 
           // Get the maximum number of simultaneous connections
           // as reported by the JDBC driver
           java.sql.DatabaseMetaData md = co.con.getMetaData();
           m_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 ((m_MaxConnections > 0) &&
             (size > m_MaxConnections)) {
           trace("WARNING: Size of pool will exceed safe maximum of " +
                 m_MaxConnections);
         }
 
         // Clear the in use flag
         co.inUse = false;
 
         // Set the last access time
         touch(co);
 
         m_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>Find the given connection in the pool
     *
     * @return Index into the pool, or -1 if not found
     */
   private int find(java.sql.Connection con)
     {
       int index = -1;
 
       // Find the matching Connection in the pool
       if ((con != null) &&
           (m_pool != null)) {
         for (int i = 0; i < m_pool.size(); i++) {
           ConnectionObject co = (ConnectionObject)
             m_pool.elementAt(i);
           if (co.con == con) {
             index = i;
             break;
           }
         }
       }
       return index;
     }
 
   /**
     * <p>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 (m_pool == null) {
         return;
       }
 
       // Get the current time in milliseconds
       long now = System.currentTimeMillis();
 
       // Check for any expired connections and remove them
       for (int i = m_pool.size() - 1; i >= 0; i--) {
         ConnectionObject co = (ConnectionObject)
           m_pool.elementAt(i);
 
         // If the connection is not in use and it has not been
         // used recently, remove it
         if (!co.inUse) {
           if ((m_ConnectionTimeout > 0) &&
               (co.lastAccess +
                (m_ConnectionTimeout * 1000) < now)) {
             removeFromPool(i);
           }
         }
       }
 
       // Remove any connections that are no longer open
       for (int i = m_pool.size() - 1; i >= 0; i--) {
         ConnectionObject co = (ConnectionObject)
           m_pool.elementAt(i);
         try {
           // If the connection is closed, remove it from the pool
           if (co.con.isClosed()) {
             //trace("Connection closed unexpectedly");
             removeFromPool(i);
           }
         }
         catch (Exception ex) {
         }
       }
 
       // Now ensure that the pool is still at it's minimum size
       try {
         if (m_pool != null) {
           if (m_pool.size() < m_ConnectionPoolSize) {
             fillPool(m_ConnectionPoolSize);
           }
         }
       }
       catch (Exception ex) {
         ex.printStackTrace();
       }
     }
 
   /**
     * <p>Sets the last access time for the given ConnectionObject
     */
   private void touch(ConnectionObject co)
     {
       if (co != null) {
         co.lastAccess = System.currentTimeMillis();
       }
     }
 
   /**
     * <p>Trace the given string
     */
   private void trace(String s)
     {
       System.out.println("ConnectionPool: " + s);
     }
 
   /**
    * just for test
    */
    public static void main(String[] args){
     System.out.println(System.getProperty("user.dir"));
     try {
       ConnectionPool cPool = new ConnectionPool();
       cPool.initialize("etc/ConnectionPool.cfg");
       java.sql.Connection con = cPool.getConnection();
       cPool.destroy();
     }
     catch(Exception ex) {
       ex.printStackTrace();
     }
 
   }
 }
 
 // This package-private class is used to represent a single
 // connection object
 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>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>Convert the object contents to a String
     */
   public String toString()
     {
       return "Connection=" + con.toString() + ",inUse=" + inUse +
         ",lastAccess=" + new Date(lastAccess) + ",useCount=" + useCount;
     }
 
 }
 
 
  ---- Power OS is FreeBSD.
 Network is computing.
 Java is network language.
 Web is Application. | 
 
 
 |