熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

Oracle數據庫 關於連接池二

2013-11-13 15:56:41  來源: Oracle 

   * 大連接數為止在返回連接給客戶程序之前它能夠驗證連接的有效性
   */
   class DBConnectionPool {
   private int checkedOut;
   private Vector freeConnections = new Vector();
   private int maxConn;
   private String name;
   private String password;
   private String URL;
   private String user;
  
   /**
   * 創建新的連接池
   *
   * @param name 連接池名字
   * @param URL 數據庫的JDBC URL
   * @param user 數據庫帳號或 null
   * @param password 密碼或 null
   * @param maxConn 此連接池允許建立的最大連接數
   */
   public DBConnectionPool(String name String URL String user String password
   int maxConn) {
   thisname = name;
   thisURL = URL;
   thisuser = user;
   thispassword = password;
   thismaxConn = maxConn;
   }
  
   /**
   * 將不再使用的連接返回給連接池
   *
   * @param con 客戶程序釋放的連接
   */
   public synchronized void freeConnection(Connection con) {
   // 將指定連接加入到向量末尾
   freeConnectionsaddElement(con);
   checkedOut;
   notifyAll();
   }
  
   /**
   * 從連接池獲得一個可用連接如沒有空閒的連接且當前連接數小於最大連接
   * 數限制則創建新連接如原來登記為可用的連接不再有效則從向量刪除之
   * 然後遞歸調用自己以嘗試新的可用連接
   */
   public synchronized Connection getConnection() {
   Connection con = null;
   if (freeConnectionssize() > ) {
   // 獲取向量中第一個可用連接
   con = (Connection) freeConnectionsfirstElement();
   freeConnectionsremoveElementAt();
   try {
   if (conisClosed()) {
   log(從連接池 + name+刪除一個無效連接);
   // 遞歸調用自己嘗試再次獲取可用連接
   con = getConnection();
   }
   }
   catch (SQLException e) {
   log(從連接池 + name+刪除一個無效連接);
   // 遞歸調用自己嘗試再次獲取可用連接
   con = getConnection();
   }
   }
   else if (maxConn == || checkedOut < maxConn) {
   con = newConnection();
   }
   if (con != null) {
   checkedOut++;
   }
   return con;
   }
  
   /**
   * 從連接池獲取可用連接可以指定客戶程序能夠等待的最長時間\\r
  
   * 參見前一個getConnection()方法
   *
   * @param timeout 以毫秒計的等待時間限制
   */
   public synchronized Connection getConnection(long timeout) {
   long startTime = new Date()getTime();
   Connection con;
   while ((con = getConnection()) == null) {
   try {
   wait(timeout);
   }
   catch (InterruptedException e) {}
   if ((new Date()getTime() startTime) >= timeout) {
   // wait()返回的原因是超時
   return null;
   }
   }
   return con;
   }
  
   /**
   * 關閉所有連接
   */
   public synchronized void release() {
   Enumeration allConnections = freeConnectionselements();
   while (allConnectionshasMoreElements()) {
   Connection con = (Connection) allConnectionsnextElement();
   try {
   conclose();
   log(關閉連接池 + name+中的一個連接);
   }
   catch (SQLException e) {
   log(e 無法關閉連接池 + name+中的連接);
   }
   }
   freeConnectionsremoveAllElements();
   }
  
   /**
   * 創建新的連接
   */
   private Connection newConnection() {
   Connection con = null;
   try {
   if (user == null) {
   con = DriverManagergetConnection(URL);
   }
   else {
   con = DriverManagergetConnection(URL user password);
   }
   log(連接池 + name+創建一個新的連接);
   }
   catch (SQLException e) {
   log(e 無法創建下列URL的連接: + URL);
   return null;
   }
   return con;
   }
   }
   }
  
  三類DBConnectionPool說明
  
  該類在行實現它表示指向某個數據庫的連接池數據庫由JDBC URL標識一個JDBC URL由三部分組成協議標識(總是jdbc)驅動程序標識(如 odbcidboracle等)數據庫標識(其格式依賴於驅動程序)例如jdbc:odbc:demo即是一個指向demo數據庫的JDBC URL而且訪問該數據庫要使用JDBCODBC驅動程序每個連接池都有一個供客戶程序使用的名字以及可選的用戶帳號密碼最大連接數限制如果Web應用程序所支持的某些數據庫操作可以被所有用戶執行而其它一些操作應由特別許可的用戶執行則可以為兩類操作分別定義連接池兩個連接池使用相同的JDBC URL但使用不同的帳號和密碼
  
  類DBConnectionPool的建構函數需要上述所有數據作為其參數行所示這些數據被保存為它的實例變量
  
  如行所示 客戶程序可以使用DBConnectionPool類提供的兩個方法獲取可用連接兩者的共同之處在於如連接池中存在可用連接則直接返回否則創建新的連接並返回如果沒有可用連接且已有連接總數等於最大限制數第一個方法將直接返回null而第二個方法將等待直到有可用連接為止
  
  所有的可用連接對象均登記在名為freeConnections的向量(Vector)中如果向量中有多於一個的連接getConnection()總是選取第一個同時由於新的可用連接總是從尾部加入向量從而使得數據庫連接由於長時間閒置而被關閉的風險減低到最小程度
  
  第一個getConnection()在返回可用連接給客戶程序之前調用了isClosed()方法驗證連接仍舊有效如果該連接被關閉或觸發異常getConnection()遞歸地調用自己以嘗試獲取另外的可用連接如果在向量freeConnections中不存在任何可用連接getConnection()方法檢查是否已經指定最大連接數限制如已經指定則檢查當前連接數是否已經到達極限此處maxConn為表示沒有限制如果沒有指定最大連接數限制或當前連接數小於該值該方法嘗試創建新的連接如創建成功則增加已使用連接的計數並返回否則返回空值
  
  如行所示創建新連接由newConnection()方法實現創建過程與是否已經指定數據庫帳號密碼有關
  
  JDBC的DriverManager類提供多個getConnection()方法這些方法要用到JDBC URL與其它一些參數如用戶帳號和密碼等DriverManager將使用指定的JDBC URL確定適合於目標數據庫的驅動程序及建立連接
  
  在行實現的第二個getConnection()方法需要一個以毫秒為單位的時間參數該參數表示客戶程序能夠等待的最長時間建立連接的具體操作仍舊由第一個getConnection()方法實現
  
  該方法執行時先將startTime初始化為當前時間在while循環中嘗試獲得一個連接如果失敗則以給定的時間值為參數調用wait()wait()的返回可能是由於其它線程調用notify()或notifyAll()也可能是由於預定時間已到為找出wait()返回的真正原因程序用當前時間減開始時間(startTime)如差值大於預定時間則返回空值否則再次調用getConnection()
  
  把空閒的連接登記到連接池由行的freeConnection()方法實現它的參數為返回給連接池的連接對象該對象被加入到freeConnections向量的末尾然後減少已使用連接計數調用notifyAll()是為了通知其它正在等待可用連接的線程
  
  許多Servlet引擎為實現安全關閉提供多種方法數據庫連接池需要知道該事件以保證所有連接能夠正常關閉DBConnectionManager類負協調整個關閉過程但關閉連接池中所有連接的任務則由DBConnectionPool類負責行實現的release()方法供DBConnectionManager調用該方法遍歷freeConnections向量並關閉所有連接然後從向量中刪除這些連接
  
  類DBConnectionManager 說明\
  
  該類只能創建一個實例其它對象能夠調用其靜態方法(也稱為類方法)獲得該唯一實例的引用行所示DBConnectionManager類的建構函數是私有的這是為了避免其它對象創建該類的實例
  
  DBConnectionManager類的客戶程序可以調用getInstance()方法獲得對該類唯一實例的引用行所示類的唯一實例在getInstance()方法第一次被調用期間創建此後其引用就一直保存在靜態變量instance中每次調用getInstance()都增加一個DBConnectionManager的客戶程序計數該計數代表引用DBConnectionManager唯一實例的客戶程序總數它將被用於控制連接池的關閉操作
  
  該類實例的初始化工作由行之間的私有方法init()完成其中 getResourceAsStream()方法用於定位並打開外部文件外部文件的定位方法依賴於類裝載器的實現標准的本地類裝載器查找操作總是開始於類文件所在路徑也能夠搜索CLASSPATH中聲明的路徑dbproperties是一個屬性文件它包含定義連接池的鍵值對可供定義的公用屬性如下
  
  drivers 以空格分隔的JDBC驅動程序類列表
  logfile 日志文件的絕對路徑
  
  其它的屬性和特定連接池相關其屬性名字前應加上連接池名字
  
  < poolname>url 數據庫的 JDBC URL
  < poolname>maxconn 允許建立的最大連接數表示沒有限制
  < poolname>user 用於該連接池的數據庫帳號
  < poolname>password 相應的密碼
  其中url屬性是必需的而其它屬性則是可選的數據庫帳號和密碼必須合法用於Windows平台的dbproperties文件示例如下
  
  drivers=sunjdbcodbcJdbcOdbcDriver jdbcidbDriver
  logfile=D:\\user\\src\\java\\DBConnectionManager\\logtxt
  
  idburl=jdbc:idb:c:\\local\\javawebserver\\db\\dbprp
  idbmaxconn=
  
  accessurl=jdbc:odbc:demo
  accessuser=demo
  accesspassword=demopw
  
  注意在Windows路徑中的反斜槓必須輸入這是由於屬性文件中的反斜槓同時也是一個轉義字符
  
  init()方法在創建屬性對象並讀取dbproperties文件之後就開始檢查logfile屬性如果屬性文件中沒有指定日志文件則默認為當前目錄下的DBConnectionManagerlog文件如日志文件無法使用則向Systemerr輸出日志記錄
  
  裝載和注冊所有在drivers屬性中指定的JDBC驅動程序由行之間的loadDrivers()方法實現該方法先用StringTokenizer將drivers屬性值分割為對應於驅動程序名稱的字符串然後依次裝載這些類並創建其實例最後在 DriverManager中注冊該實例並把它加入到一個私有的向量drivers向量drivers將用於關閉服務時從DriverManager取消所有JDBC 驅動程序的注冊
  
  init()方法的最後一個任務是調用私有方法createPools()創建連接池對象行所示createPools()方法先創建所有屬性名字的枚舉對象(即Enumeration對象該對象可以想象為一個元素系列逐次調用其nextElement()方法將順序返回各元素)然後在其中搜索名字以url結尾的屬性對於每一個符合條件的屬性先提取其連接池名字部分進而讀取所有屬於該連接池的屬性最後創建連接池對象並把它保存在實例變量pools中散列表(Hashtable類 )pools實現連接池名字到連接池對象之間的映射此處以連接池名字為鍵連接池對象為值
  
  為便於客戶程序從指定連接池獲得可用連接或將連接返回給連接池類DBConnectionManager提供了方法getConnection()和freeConnection()所有這些方法都要求在參數中指定連接池名字具體的連接獲取或返回操作則調用對應的連接池對象完成它們的實現分別在
  
  如行所示為實現連接池的安全關閉DBConnectionManager提供了方法release()在上面我們已經提到所有DBConnectionManager的客戶程序都應該調用靜態方法getInstance()以獲得該管理器的引用此調用將增加客戶程序計數客戶程序在關閉時調用release()可以遞減該計數當最後一個客戶程序調用release()遞減後的引用計數為就可以調用各個連接池的release()方法關閉所有連接了管理類release()方法最後的任務是撤銷所有JDBC驅動程序的注冊
  
  Servlet使用連接池示例
  
  Servlet API所定義的Servlet生命周期類如
  
  ) 創建並初始化Servlet(init()方法)
  ) 響應客戶程序的服務請求(service()方法)
  ) Servlet終止運行釋放所有資源(destroy()方法)
  
  本例演示連接池應用上述關鍵步驟中的相關操作為
  
  ) 在init()用實例變量connMgr 保存調用DBConnectionManagergetInstance()所返回的引用
  ) 在service()調用getConnection()執行數據庫操作用freeConnection()將連接返回給連接池
  ) 在destroy()調用release()關閉所有連接釋放所有資源
  
  示例程序清單如下
  
  import javaio*;import javasql*;import javaxservlet*;import javaxservlethttp*;public class TestServlet extends HttpServlet { private DBConnectionManager connMgr; public void init(ServletConfig conf) throws ServletException { superinit(conf); connMgr = DBConnectionManagergetInstance(); } public void service(HttpServletRequest req HttpServletResponse res) throws IOException { ressetContentType(text/html); PrintWriter out = resgetWriter(); Connection con = connMgrgetConnection(idb); if (con == null) { outprintln(不能獲取數據庫連接); return; } ResultSet rs = null; ResultSetMetaData md = null; Statement stmt = null; try { stmt = concreateStatement(); rs = stmtexecuteQuery(SELECT * FROM EMPLOYEE); md = rsgetMetaData(); outprintln(< H>職工數據< /H>); while (rsnext()) { outprintln(< BR>); for (int i = ; i < mdgetColumnCount(); i++) { outprint(rsgetString(i) + ); } } stmtclose(); rsclose(); } catch (SQLException e) { eprintStackTrace(out); } connMgrfreeConnection(idb con); } public void destroy() { connMgrrelease(); superdestroy(); }}
   con); } public void destroy() { connMgrrelease(); superdestroy(); }}
From:http://tw.wingwit.com/Article/program/Oracle/201311/17555.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.