posts - 22,comments - 35,trackbacks - 0
  1 package  ConnectionPool; 
  2 /**  
  3 此内部类定义了一个连接池。它能够根据要求创建新连接,直到预定的最大连接数为止。在返回连接给客户程序之前,它能够 
  4 验证连接的有效性。此类提供以下功能: 
  5 1.从连接池获取(或创建)可用连接 
  6 2.把连接返回给连接池 
  7 3.在系统关闭时释放所有资源,关闭所有连接 
  8 4.处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题) 
  9 5.限制连接池中的连接总数不超过某个预定值 
 10 */
 
 11 import  java.io. *
 12 import  java.sql. *
 13 import  java.util. *
 14 import  java.util.Date; 
 15
 16 class  DBConnectionPool 
 17
 18      private   int  checkedOut; 
 19      private  PrintWriter logPrint; 
 20      private  Vector freeConnections  =   new  Vector(); 
 21      private   int  maxConn; 
 22      private  String name; 
 23      private  String password; 
 24      private  String URL; 
 25      private  String user; 
 26     
 27      /**  
 28     创建新的连接池 
 29     * @param  name 连接池名字 
 30     * @param  URL 数据库的JDBC URL 
 31     * @param  user 数据库帐号,或null 
 32     * @param  password 密码,或null 
 33     * @param  maxConn 此连接池允许建立的最大连接数 
 34      */
 
 35      public  DBConnectionPool(String name, String URL, String user, String password,  int  maxConn) 
 36          this .name  =  name; 
 37          this .URL  =  URL; 
 38          this .user  =  user; 
 39          this .password  =  password; 
 40          this .maxConn  =  maxConn; 
 41         InputStream is  =  getClass().getResourceAsStream( " /db.properties " ); 
 42         Properties dbProps  =   new  Properties(); 
 43          try  
 44             dbProps.load(is); 
 45         }
 
 46          catch (Exception e) 
 47             System.err.println( " 不能读取属性文件. "   +   " 请确保db.properties在CLASSPATH指定的路径中 " ); 
 48              return
 49         }
 
 50         String logFile  =  dbProps.getProperty( " Poollogfile " " DBConnectionPool.log " ); 
 51          try  
 52             logPrint  =   new  PrintWriter( new  FileWriter(logFile,  true ),  true ); 
 53         }
 
 54          catch (IOException e) 
 55             System.err.println( " 无法打开日志文件: "   +  logFile); 
 56             logPrint  =   new  PrintWriter(System.err); 
 57         }
 
 58     }
 
 59     
 60     
 61      /**  
 62     将不再使用的连接返回给连接池 
 63     * @param  con 客户程序释放的连接 
 64      */
 
 65      public   synchronized   void  freeConnection(Connection con) 
 66         freeConnections.addElement(con); 
 67         checkedOut --
 68         notifyAll(); 
 69     }
 
 70     
 71     
 72      /**  
 73     从连接池获得一个可用连接,如没有空闲的连接且当前连接数小于最大连接数,则创建新连接, 
 74     如原来登记为可用的连接不再有效,则从向量删除之,然后递归调用自己以尝试新的可用连接 
 75      */
 
 76      public   synchronized  Connection getConnection() 
 77         Connection con  =   null
 78          if (freeConnections.size()  >   0 {   //  获取向量中第一个可用连接 
 79             con  =  (Connection)freeConnections.firstElement(); 
 80             freeConnections.removeElementAt( 0 ); 
 81              try  
 82                  if (con.isClosed()) 
 83                     log( " 从连接池 "   +  name  +   " 删除一个无效连接 " ); 
 84                     con  =  getConnection(); 
 85                 }
 
 86             }
 
 87              catch (SQLException e) 
 88                 log( " 从连接池 "   +  name  +   " 删除一个无效连接 " ); 
 89                 con  =  getConnection(); 
 90             }
 
 91         }
 
 92          else   if (maxConn  ==   0   ||  checkedOut  <  maxConn) 
 93             con  =  newConnection(); 
 94         }
 
 95          if (con  !=   null
 96             checkedOut ++
 97         }
 
 98          return  con; 
 99     }
 
100     
101     
102      /**  
103     从连接池获取可用连接,可以指定客户程序能够等待的最长时间 
104     * @param  timeout 以毫秒计的等待时间限制 
105      */
 
106      public   synchronized  Connection getConnection( long  timeout) 
107          long  startTime  =   new  Date().getTime(); 
108         Connection con; 
109          while ((con  =  getConnection())  ==   null
110              try  
111                 wait(timeout); 
112             }
 
113              catch (InterruptedException e) {}  
114             
115              if (( new  Date().getTime()  -  startTime)  >=  timeout) 
116                  return   null
117             }
 
118         }
 
119          return  con; 
120     }
 
121     
122     
123      /**  
124     关闭所有连接 
125      */
 
126      public   synchronized   void  release() 
127         Enumeration allConnections  =  freeConnections.elements(); 
128          while (allConnections.hasMoreElements()) 
129             Connection con  =  (Connection)allConnections.nextElement(); 
130              try  
131                 con.close(); 
132                 log( " 关闭连接池 "   +  name  +   " 中的一个连接 " ); 
133             }
 
134              catch (SQLException e) 
135                 log(e,  " 无法关闭连接池 "   +  name  +   " 中的连接 " ); 
136             }
 
137         }
 
138         freeConnections.removeAllElements(); 
139     }
 
140     
141     
142      /**  
143     创建新的连接 
144      */
 
145      private  Connection newConnection() 
146         Connection con  =   null
147          try  
148              if (user  ==   null
149                 con  =  DriverManager.getConnection(URL); 
150             }
 
151              else  
152                 con  =  DriverManager.getConnection(URL, user, password); 
153             }
 
154             log( " 连接池 "   +  name  +   " 创建一个新的连接 " ); 
155         }
 
156          catch (SQLException e) 
157             log(e,  " 无法创建下列URL的连接 "   +  URL); 
158              return   null
159         }
 
160          return  con; 
161     }
 
162     
163     
164      /**  
165     将文本信息写入日志文件 
166     缺省为packaged 
167      */
 
168      void  log(String msg) 
169         logPrint.println( new  Date()  +   " "   +  msg); 
170     }
 
171     
172     
173      /**  
174     将文本信息与异常写入日志文件 
175      */
 
176      void  log(Throwable e, String msg) 
177         logPrint.println( new  Date()  +   " "   +  msg); 
178         e.printStackTrace(logPrint); 
179     }
 
180 }
 


  1 package  ConnectionPool; 
  2
  3 /* 此类用于管理多个连接池对象,它支持对一个或多个由属性文件定义的数据库连接池的访问,客户程序可以调用getInstance()方法访问本类的唯一实例。它提供以下功能: 
  4 1.装载和注册JDBC驱动程序 
  5 2.根据在属性文件中定义的属性创建连接池对象 
  6 3.实现连接池名字与其实例之间的映射 
  7 4.跟踪客户程序对连接池的引用,保证在最后一个客户程序结束时安全地关闭所有连接池 
  8 */
 
  9
 10 import  java.io. *
 11 import  java.sql. *
 12 import  java.util. *
 13 // import com.supersoftintl.intranet.common.DBConnectionPool; 
 14 // import java.util.Date; 
 15 /**  
 16 * 管理类DBConnectionManager支持对一个或多个由属性文件定义的数据库连接 
 17 * 池的访问.客户程序可以调用getInstance()方法访问本类的唯一实例. 
 18 */
 
 19 public   class  DBConnectionManager 
 20      static   private  DBConnectionManager instance; /* 唯一实例 */  
 21      static   private   int  clients;
 22       /* 该计数代表引用DBConnectionManager唯一实例的客户程序总数, 
 23     它将被用于控制连接池的关闭操作  */
 
 24     
 25      static   private  String DEFAULTCONNECTIONPOOL  =   " ConnectionPool "
 26      private  Vector drivers  =   new  Vector(); 
 27      private  PrintWriter logPrint; 
 28      private  Hashtable pools  =   new  Hashtable(); 
 29     
 30      /**  
 31     返回唯一实例。如果是第一次调用此方法,则创建实例 
 32      */
 
 33      static   synchronized   public  DBConnectionManager getInstance() 
 34          if (instance  ==   null
 35             instance  =   new  DBConnectionManager(); 
 36         }
 
 37         clients ++
 38          return  instance; 
 39     }
 
 40     
 41     
 42      /**  
 43     建构函数私有以防止其它对象创建本类实例 
 44      */
 
 45      public  DBConnectionManager() 
 46         init(); 
 47     }

 48     
 49     
 50      /**  Added by leo on 2001-5-23 
 51     使用默认的连接池名,创建并返回新连接 
 52     * 
 53     *  @return  Connection 可用连接或null 
 54      */
 
 55      public  Connection getConnection() 
 56          return  getConnection(DEFAULTCONNECTIONPOOL); 
 57     }
 
 58     
 59     
 60      /**  
 61     获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数 
 62     限制,则创建并返回新连接 
 63     * 
 64     *  @param  name 在属性文件中定义的连接池名字 
 65     *  @return  Connection 可用连接或null 
 66      */
 
 67      public  Connection getConnection(String name) 
 68         DBConnectionPool pool  =  (DBConnectionPool)pools.get(name); 
 69          if (pool  !=   null
 70              return  pool.getConnection(); 
 71         }
 
 72          return   null
 73     }
 
 74     
 75     
 76      /**  
 77     获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制, 
 78     则创建并返回新连接.否则,在指定的时间内等待其它线程释放连接. 
 79     * 
 80     *  @param  name 连接池名字 
 81     *  @param  time 以毫秒计的等待时间 
 82     *  @return  Connection 可用连接或null 
 83      */
 
 84      public  Connection getConnection(String name,  long  time) 
 85         DBConnectionPool pool  =  (DBConnectionPool)pools.get(name); 
 86          if (pool  !=   null
 87              return  pool.getConnection(time); 
 88         }
 
 89          return   null
 90     }
 
 91     
 92     
 93      /**  Added by leo on 2001-5-23 
 94     将连接对象返回给默认的连接池 
 95     * 
 96     *  @param  con 连接对象 
 97      */
 
 98      public   void  freeConnection(Connection con) 
 99         String name  =  DEFAULTCONNECTIONPOOL; 
100         freeConnection(name,con); 
101     }
 
102     
103     
104      /**  
105     将连接对象返回给由名字指定的连接池 
106     * 
107     *  @param  name 在属性文件中定义的连接池名字 
108     *  @param  con 连接对象 
109      */
 
110      public   void  freeConnection(String name, Connection con) 
111         DBConnectionPool pool  =  (DBConnectionPool)pools.get(name); 
112          if (pool  !=   null
113             pool.freeConnection(con); 
114         }
 
115     }
 
116     
117     
118      /**  
119     关闭所有连接,撤销驱动程序的注册 
120      */
 
121      public   synchronized   void  release()  //  等待直到最后一个客户程序调用 
122          if ( -- clients  !=   0
123              return
124         }
 
125         Enumeration allPools  =  pools.elements(); 
126          while (allPools.hasMoreElements()) 
127             DBConnectionPool pool  =  (DBConnectionPool)allPools.nextElement(); 
128             pool.release(); 
129         }
 
130         Enumeration allDrivers  =  drivers.elements(); 
131          while (allDrivers.hasMoreElements()) 
132             Driver driver  =  (Driver)allDrivers.nextElement(); 
133              try  
134                 DriverManager.deregisterDriver(driver); 
135                 log( " 撤消JDBC驱动程序 "   +  driver.getClass().getName()  +   " 的注册 " ); 
136             }
 
137              catch (SQLException e) 
138                 log(e,  " 无法撤消下列JDBC驱动程序的注册 "   +  driver.getClass().getName()); 
139             }
 
140         }
 
141     }
 
142     
143     
144      /**  
145     根据指定属性创建连接池实例. 
146     * 
147     *  @param  props 连接池属性 
148      */
 
149      private   void  createPools(Properties props) 
150         Enumeration propNames  =  props.propertyNames(); 
151          while (propNames.hasMoreElements()) 
152             String name  =  (String)propNames.nextElement(); 
153              if (name.endsWith( " .url " )) 
154                 String poolName  =  name.substring( 0 , name.lastIndexOf( " . " )); 
155                 String url  =  props.getProperty(poolName  +   " .url " ); 
156                  if (url  ==   null
157                     log( " 没有为连接池 "   +  poolName  +   " 指定URL " ); 
158                      continue
159                 }
 
160                 String user  =  props.getProperty(poolName  +   " .user " ); 
161                 String password  =  props.getProperty(poolName  +   " .password " ); 
162                 String maxconn  =  props.getProperty(poolName  +   " .maxconn " " 0 " ); 
163                  int  max; 
164                  try  
165                     max  =  Integer.valueOf(maxconn).intvalue(); 
166                 }
 
167                  catch (NumberformatException e) 
168                     log( " 错误的最大连接数限制: "   +  maxconn  +   " .连接池: "   +  poolName); 
169                     log( " 自动改变设置为0--即无限制 " ); 
170                     max  =   0
171                 }
 
172                 DBConnectionPool pool  =   new  DBConnectionPool(poolName, url, user, password, max); 
173                 pools.put(poolName, pool); 
174                 log( " 成功创建连接池 "   +  poolName); 
175             }
 
176         }
 
177     }
 
178     
179     
180      /**  
181     读取属性完成初始化 
182      */
 
183      private   void  init() 
184         InputStream is  =  getClass().getResourceAsStream( " /db.properties " ); 
185         Properties dbProps  =   new  Properties(); 
186          try  
187             dbProps.load(is); 
188         }
 
189          catch (Exception e) 
190             System.err.println( " 不能读取属性文件. "   +   " 请确保db.properties在CLASSPATH指定的路径中 " ); 
191              return
192         }
 
193         String logFile  =  dbProps.getProperty( " Managerlogfile " " DBConnectionManager.log " ); 
194          try  
195             logPrint  =   new  PrintWriter( new  FileWriter(logFile,  true ),  true ); 
196         }
 
197          catch (IOException e) 
198             System.err.println( " 无法打开日志文件: "   +  logFile); 
199             logPrint  =   new  PrintWriter(System.err); 
200         }
 
201         loadDrivers(dbProps); 
202         createPools(dbProps); 
203     }
 
204     
205     
206      /**  
207     装载和注册所有JDBC驱动程序 
208     * 
209     *  @param  props 属性 
210      */
 
211      private   void  loadDrivers(Properties props) 
212         String driverClasses  =  props.getProperty( " drivers " ); 
213         StringTokenizer st  =   new  StringTokenizer(driverClasses); 
214          while (st.hasMoreElements()) 
215             String driverClassName  =  st.nextToken().trim(); 
216              try  
217                 Driver driver  =  (Driver)Class.forName(driverClassName).newInstance(); 
218                 DriverManager.registerDriver(driver); 
219                 drivers.addElement(driver); 
220                 log( " 成功JDBC注册驱动程序 "   +  driverClassName); 
221             }
 
222              catch (Exception e) 
223                 log( " 无法注册JDBC驱动程序; "   +  driverClassName  +   " ,错误: "   +  e); 
224             }
 
225         }
 
226     }
 
227     
228     
229      /**  
230     将文本信息写入日志文件 
231     缺省为packaged 
232      */
 
233      void  log(String msg) 
234         logPrint.println( new  java.util.Date()  +   " "   +  msg); 
235     }
 
236     
237     
238      /**  
239     将文本信息与异常写入日志文件 
240      */
 
241      void  log(Throwable e, String msg) 
242         logPrint.println( new  java.util.Date()  +   " "   +  msg); 
243         e.printStackTrace(logPrint); 
244     }
 
245 }
 
posted on 2006-06-29 14:44 kelven 阅读(2161) 评论(0)  编辑  收藏 所属分类: java

只有注册用户登录后才能发表评论。


网站导航: