日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

连结池详解

發(fā)布時(shí)間:2025/3/14 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 连结池详解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
到目前為目,JDBC2的連結(jié)池只是一個(gè)接口,沒有真正的實(shí)現(xiàn),JDBC3正在開發(fā)中,
據(jù)報(bào)已經(jīng)支持連結(jié)池,但..........
JDBC3用了JNDI技術(shù),連結(jié)池的配置可以讓一個(gè)高手都煩死.

目前第三方已經(jīng)實(shí)現(xiàn)的連結(jié)池當(dāng)然是poolman,1.0版對(duì)一般用戶來說已經(jīng)足夠用了.配置也簡單,2.0版雖然增加了一些功能,但配置也是采用JNDI,對(duì)RMI和EJB不懂的朋友可能很煩.建議用1.0的了.

如果有興趣,自己也可以實(shí)現(xiàn)連結(jié)池,最關(guān)鍵的技術(shù)也就是把連結(jié)作為參數(shù)傳給一個(gè)BEAN,用完后返回這個(gè)參數(shù)連結(jié)而不是關(guān)閉.
下面是一個(gè)簡單的實(shí)現(xiàn):
DBConnectionManager.java程序清單如下:
????
????001?import?java.io.*;
????002?import?java.sql.*;
????003?import?java.util.*;
????004?import?java.util.Date;
????005
????006?/**
????007?*?管理類DBConnectionManager支持對(duì)一個(gè)或多個(gè)由屬性文件定義的數(shù)據(jù)庫連接
????008?*?池的訪問.客戶程序可以調(diào)用getInstance()方法訪問本類的唯一實(shí)例.
????009?*/
????010?public?class?DBConnectionManager?{
????011?static?private?DBConnectionManager?instance;?//?唯一實(shí)例
????012?static?private?int?clients;
????013
????014?private?Vector?drivers?=?new?Vector();
????015?private?PrintWriter?log;
????016?private?Hashtable?pools?=?new?Hashtable();
????017
????018?/**
????019?*?返回唯一實(shí)例.如果是第一次調(diào)用此方法,則創(chuàng)建實(shí)例
????020?*
????021?*?@return?DBConnectionManager?唯一實(shí)例
????022?*/
????023?static?synchronized?public?DBConnectionManager?getInstance()?{
????024?if?(instance?==?null)?{
????025?instance?=?new?DBConnectionManager();
????026?}
????027?clients++;
????028?return?instance;
????029?}
????030
????031?/**
????032?*?建構(gòu)函數(shù)私有以防止其它對(duì)象創(chuàng)建本類實(shí)例
????033?*/
????034?private?DBConnectionManager()?{
????035?init();
????036?}
????037
????038?/**
????039?*?將連接對(duì)象返回給由名字指定的連接池
????040?*
????041?*?@param?name?在屬性文件中定義的連接池名字
????042?*?@param?con?連接對(duì)象
????043?*/
????044?public?void?freeConnection(String?name,?Connection?con)?{
????045?DBConnectionPool?pool?=?(DBConnectionPool)?pools.get(name);
????046?if?(pool?!=?null)?{
????047?pool.freeConnection(con);
????048?}
????049?}
????050
????051?/**
????052?*?獲得一個(gè)可用的(空閑的)連接.如果沒有可用連接,且已有連接數(shù)小于最大連接數(shù)
????053?*?限制,則創(chuàng)建并返回新連接
????054?*
????055?*?@param?name?在屬性文件中定義的連接池名字
????056?*?@return?Connection?可用連接或null
????057?*/
????058?public?Connection?getConnection(String?name)?{
????059?DBConnectionPool?pool?=?(DBConnectionPool)?pools.get(name);
????060?if?(pool?!=?null)?{
????061?return?pool.getConnection();
????062?}
????063?return?null;
????064?}
????065
????066?/**
????067?*?獲得一個(gè)可用連接.若沒有可用連接,且已有連接數(shù)小于最大連接數(shù)限制,
????068?*?則創(chuàng)建并返回新連接.否則,在指定的時(shí)間內(nèi)等待其它線程釋放連接.
????069?*
????070?*?@param?name?連接池名字
????071?*?@param?time?以毫秒計(jì)的等待時(shí)間
????072?*?@return?Connection?可用連接或null
????073?*/
????074?public?Connection?getConnection(String?name,?long?time)?{
????075?DBConnectionPool?pool?=?(DBConnectionPool)?pools.get(name);
????076?if?(pool?!=?null)?{
????077?return?pool.getConnection(time);
????078?}
????079?return?null;
????080?}
????081
????082?/**
????083?*?關(guān)閉所有連接,撤銷驅(qū)動(dòng)程序的注冊(cè)
????084?*/
????085?public?synchronized?void?release()?{
????086?//?等待直到最后一個(gè)客戶程序調(diào)用
????087?if?(--clients?!=?0)?{
????088?return;
????089?}
????090
????091?Enumeration?allPools?=?pools.elements();
????092?while?(allPools.hasMoreElements())?{
????093?DBConnectionPool?pool?=?(DBConnectionPool)?allPools.nextElement();
????094?pool.release();
????095?}
????096?Enumeration?allDrivers?=?drivers.elements();
????097?while?(allDrivers.hasMoreElements())?{
????098?Driver?driver?=?(Driver)?allDrivers.nextElement();
????099?try?{
????100?DriverManager.deregisterDriver(driver);
????101?log("撤銷JDBC驅(qū)動(dòng)程序?"?+?driver.getClass().getName()+"的注冊(cè)\\");
????102?}
????103?catch?(SQLException?e)?{
????104?log(e,?"無法撤銷下列JDBC驅(qū)動(dòng)程序的注冊(cè):?"?+?driver.getClass().getName());
????105?}
????106?}
????107?}
????108
????109?/**
????110?*?根據(jù)指定屬性創(chuàng)建連接池實(shí)例.
????111?*
????112?*?@param?props?連接池屬性
????113?*/
????114?private?void?createPools(Properties?props)?{
????115?Enumeration?propNames?=?props.propertyNames();
????116?while?(propNames.hasMoreElements())?{
????117?String?name?=?(String)?propNames.nextElement();
????118?if?(name.endsWith(".url"))?{
????119?String?poolName?=?name.substring(0,?name.lastIndexOf("."));
????120?String?url?=?props.getProperty(poolName?+?".url");
????121?if?(url?==?null)?{
????122?log("沒有為連接池"?+?poolName?+?"指定URL");
????123?continue;
????124?}
????125?String?user?=?props.getProperty(poolName?+?".user");
????126?String?password?=?props.getProperty(poolName?+?".password");
????127?String?maxconn?=?props.getProperty(poolName?+?".maxconn",?"0");
????128?int?max;
????129?try?{
????130?max?=?Integer.valueOf(maxconn).intValue();
????131?}
????132?catch?(NumberFormatException?e)?{
????133?log("錯(cuò)誤的最大連接數(shù)限制:?"?+?maxconn?+?"?.連接池:?"?+?poolName);
????134?max?=?0;
????135?}
????136?DBConnectionPool?pool?=
????137?new?DBConnectionPool(poolName,?url,?user,?password,?max);
????138?pools.put(poolName,?pool);
????139?log("成功創(chuàng)建連接池"?+?poolName);
????140?}
????141?}
????142?}
????143
????144?/**
????145?*?讀取屬性完成初始化
????146?*/
????147?private?void?init()?{
????148?InputStream?is?=?getClass().getResourceAsStream("/db.properties");
????149?Properties?dbProps?=?new?Properties();
????150?try?{
????151?dbProps.load(is);
????152?}
????153?catch?(Exception?e)?{
????154?System.err.println("不能讀取屬性文件.?"?+
????155?"請(qǐng)確保db.properties在CLASSPATH指定的路徑中");
????156?return;
????157?}
????158?String?logFile?=?dbProps.getProperty("logfile",?"DBConnectionManager.log");
????159?try?{
????160?log?=?new?PrintWriter(new?FileWriter(logFile,?true),?true);
????161?}
????162?catch?(IOException?e)?{
????163?System.err.println("無法打開日志文件:?"?+?logFile);
????164?log?=?new?PrintWriter(System.err);
????165?}
????166?loadDrivers(dbProps);
????167?createPools(dbProps);
????168?}
????169
????170?/**
????171?*?裝載和注冊(cè)所有JDBC驅(qū)動(dòng)程序
????172?*
????173?*?@param?props?屬性
????174?*/
????175?private?void?loadDrivers(Properties?props)?{
????176?String?driverClasses?=?props.getProperty("drivers");
????177?StringTokenizer?st?=?new?StringTokenizer(driverClasses);
????178?while?(st.hasMoreElements())?{
????179?String?driverClassName?=?st.nextToken().trim();
????180?try?{
????181?Driver?driver?=?(Driver)
????182?Class.forName(driverClassName).newInstance();
????183?DriverManager.registerDriver(driver);
????184?drivers.addElement(driver);
????185?log("成功注冊(cè)JDBC驅(qū)動(dòng)程序\\"?+?driverClassName);
????186?}
????187?catch?(Exception?e)?{
????188?log("無法注冊(cè)JDBC驅(qū)動(dòng)程序:?"?+
????189?driverClassName?+?",?錯(cuò)誤:?"?+?e);
????190?}
????191?}
????192?}
????193
????194?/**
????195?*?將文本信息寫入日志文件
????196?*/
????197?private?void?log(String?msg)?{
????198?log.println(new?Date()?+?":?"?+?msg);
????199?}
????200
????201?/**
????202?*?將文本信息與異常寫入日志文件
????203?*/
????204?private?void?log(Throwable?e,?String?msg)?{
????205?log.println(new?Date()?+?":?"?+?msg);
????206?e.printStackTrace(log);
????207?}
????208
????209?/**
????210?*?此內(nèi)部類定義了一個(gè)連接池.它能夠根據(jù)要求創(chuàng)建新連接,直到預(yù)定的最
????211?*?大連接數(shù)為止.在返回連接給客戶程序之前,它能夠驗(yàn)證連接的有效性.
????212?*/
????213?class?DBConnectionPool?{
????214?private?int?checkedOut;
????215?private?Vector?freeConnections?=?new?Vector();
????216?private?int?maxConn;
????217?private?String?name;
????218?private?String?password;
????219?private?String?URL;
????220?private?String?user;
????221
????222?/**
????223?*?創(chuàng)建新的連接池
????224?*
????225?*?@param?name?連接池名字
????226?*?@param?URL?數(shù)據(jù)庫的JDBC?URL
????227?*?@param?user?數(shù)據(jù)庫帳號(hào),或?null
????228?*?@param?password?密碼,或?null
????229?*?@param?maxConn?此連接池允許建立的最大連接數(shù)
????230?*/
????231?public?DBConnectionPool(String?name,?String?URL,?String?user,?String?password,
????232?int?maxConn)?{
????233?this.name?=?name;
????234?this.URL?=?URL;
????235?this.user?=?user;
????236?this.password?=?password;
????237?this.maxConn?=?maxConn;
????238?}
????239
????240?/**
????241?*?將不再使用的連接返回給連接池
????242?*
????243?*?@param?con?客戶程序釋放的連接
????244?*/
????245?public?synchronized?void?freeConnection(Connection?con)?{
????246?//?將指定連接加入到向量末尾
????247?freeConnections.addElement(con);
????248?checkedOut--;
????249?notifyAll();
????250?}
????251
????252?/**
????253?*?從連接池獲得一個(gè)可用連接.如沒有空閑的連接且當(dāng)前連接數(shù)小于最大連接
????254?*?數(shù)限制,則創(chuàng)建新連接.如原來登記為可用的連接不再有效,則從向量刪除之,
????255?*?然后遞歸調(diào)用自己以嘗試新的可用連接.
????256?*/
????257?public?synchronized?Connection?getConnection()?{
????258?Connection?con?=?null;
????259?if?(freeConnections.size()?>?0)?{
????260?//?獲取向量中第一個(gè)可用連接
????261?con?=?(Connection)?freeConnections.firstElement();
????262?freeConnections.removeElementAt(0);
????263?try?{
????264?if?(con.isClosed())?{
????265?log("從連接池"?+?name+"刪除一個(gè)無效連接");
????266?//?遞歸調(diào)用自己,嘗試再次獲取可用連接
????267?con?=?getConnection();
????268?}
????269?}
????270?catch?(SQLException?e)?{
????271?log("從連接池"?+?name+"刪除一個(gè)無效連接");
????272?//?遞歸調(diào)用自己,嘗試再次獲取可用連接
????273?con?=?getConnection();
????274?}
????275?}
????276?else?if?(maxConn?==?0?||?checkedOut?<?maxConn)?{
????277?con?=?newConnection();
????278?}
????279?if?(con?!=?null)?{
????280?checkedOut++;
????281?}
????282?return?con;
????283?}
????284
????285?/**
????286?*?從連接池獲取可用連接.可以指定客戶程序能夠等待的最長時(shí)間
????287?*?參見前一個(gè)getConnection()方法.
????288?*
????289?*?@param?timeout?以毫秒計(jì)的等待時(shí)間限制
????290?*/
????291?public?synchronized?Connection?getConnection(long?timeout)?{
????292?long?startTime?=?new?Date().getTime();
????293?Connection?con;
????294?while?((con?=?getConnection())?==?null)?{
????295?try?{
????296?wait(timeout);
????297?}
????298?catch?(InterruptedException?e)?{}
????299?if?((new?Date().getTime()?-?startTime)?>=?timeout)?{
????300?//?wait()返回的原因是超時(shí)
????301?return?null;
????302?}
????303?}
????304?return?con;
????305?}
????306
????307?/**
????308?*?關(guān)閉所有連接
????309?*/
????310?public?synchronized?void?release()?{
????311?Enumeration?allConnections?=?freeConnections.elements();
????312?while?(allConnections.hasMoreElements())?{
????313?Connection?con?=?(Connection)?allConnections.nextElement();
????314?try?{
????315?con.close();
????316?log("關(guān)閉連接池"?+?name+"中的一個(gè)連接");
????317?}
????318?catch?(SQLException?e)?{
????319?log(e,?"無法關(guān)閉連接池"?+?name+"中的連接");
????320?}
????321?}
????322?freeConnections.removeAllElements();
????323?}
????324
????325?/**
????326?*?創(chuàng)建新的連接
????327?*/
????328?private?Connection?newConnection()?{
????329?Connection?con?=?null;
????330?try?{
????331?if?(user?==?null)?{
????332?con?=?DriverManager.getConnection(URL);
????333?}
????334?else?{
????335?con?=?DriverManager.getConnection(URL,?user,?password);
????336?}
????337?log("連接池"?+?name+"創(chuàng)建一個(gè)新的連接");
????338?}
????339?catch?(SQLException?e)?{
????340?log(e,?"無法創(chuàng)建下列URL的連接:?"?+?URL);
????341?return?null;
????342?}
????343?return?con;
????344?}
????345?}
????346?}
????
????
????三、類DBConnectionPool說明
????
????該類在209至345行實(shí)現(xiàn),它表示指向某個(gè)數(shù)據(jù)庫的連接池。數(shù)據(jù)庫由JDBC?URL標(biāo)識(shí)。一個(gè)JDBC?URL由三部分組成:協(xié)議標(biāo)識(shí)(總是jdbc),驅(qū)動(dòng)程序標(biāo)識(shí)(如?odbc、idb、oracle等),數(shù)據(jù)庫標(biāo)識(shí)(其格式依賴于驅(qū)動(dòng)程序)。例如,jdbc:odbc:demo,即是一個(gè)指向demo數(shù)據(jù)庫的JDBC?URL,而且訪問該數(shù)據(jù)庫要使用JDBC-ODBC驅(qū)動(dòng)程序。每個(gè)連接池都有一個(gè)供客戶程序使用的名字以及可選的用戶帳號(hào)、密碼、最大連接數(shù)限制。如果Web應(yīng)用程序所支持的某些數(shù)據(jù)庫操作可以被所有用戶執(zhí)行,而其它一些操作應(yīng)由特別許可的用戶執(zhí)行,則可以為兩類操作分別定義連接池,兩個(gè)連接池使用相同的JDBC?URL,但使用不同的帳號(hào)和密碼。
????類DBConnectionPool的建構(gòu)函數(shù)需要上述所有數(shù)據(jù)作為其參數(shù)。如222至238行所示,這些數(shù)據(jù)被保存為它的實(shí)例變量:
????如252至283行、285至305行所示,?客戶程序可以使用DBConnectionPool類提供的兩個(gè)方法獲取可用連接。兩者的共同之處在于:如連接池中存在可用連接,則直接返回,否則創(chuàng)建新的連接并返回。如果沒有可用連接且已有連接總數(shù)等于最大限制數(shù),第一個(gè)方法將直接返回null,而第二個(gè)方法將等待直到有可用連接為止。
????所有的可用連接對(duì)象均登記在名為freeConnections的向量(Vector)中。如果向量中有多于一個(gè)的連接,getConnection()總是選取第一個(gè)。同時(shí),由于新的可用連接總是從尾部加入向量,從而使得數(shù)據(jù)庫連接由于長時(shí)間閑置而被關(guān)閉的風(fēng)險(xiǎn)減低到最小程度。
????第一個(gè)getConnection()在返回可用連接給客戶程序之前,調(diào)用了isClosed()方法驗(yàn)證連接仍舊有效。如果該連接被關(guān)閉或觸發(fā)異常,getConnection()遞歸地調(diào)用自己以嘗試獲取另外的可用連接。如果在向量freeConnections中不存在任何可用連接,getConnection()方法檢查是否已經(jīng)指定最大連接數(shù)限制。如已經(jīng)指定,則檢查當(dāng)前連接數(shù)是否已經(jīng)到達(dá)極限。此處maxConn為0表示沒有限制。如果沒有指定最大連接數(shù)限制或當(dāng)前連接數(shù)小于該值,該方法嘗試創(chuàng)建新的連接。如創(chuàng)建成功,則增加已使用連接的計(jì)數(shù)并返回,否則返回空值。
????如325至345行所示,創(chuàng)建新連接由newConnection()方法實(shí)現(xiàn)。創(chuàng)建過程與是否已經(jīng)指定數(shù)據(jù)庫帳號(hào)、密碼有關(guān)。
????JDBC的DriverManager類提供多個(gè)getConnection()方法,這些方法要用到JDBC?URL與其它一些參數(shù),如用戶帳號(hào)和密碼等。DriverManager將使用指定的JDBC?URL確定適合于目標(biāo)數(shù)據(jù)庫的驅(qū)動(dòng)程序及建立連接。
????在285至305行實(shí)現(xiàn)的第二個(gè)getConnection()方法需要一個(gè)以毫秒為單位的時(shí)間參數(shù),該參數(shù)表示客戶程序能夠等待的最長時(shí)間。建立連接的具體操作仍舊由第一個(gè)getConnection()方法實(shí)現(xiàn)。
????該方法執(zhí)行時(shí)先將startTime初始化為當(dāng)前時(shí)間。在while循環(huán)中嘗試獲得一個(gè)連接。如果失敗,則以給定的時(shí)間值為參數(shù)調(diào)用wait()。wait()的返回可能是由于其它線程調(diào)用notify()或notifyAll(),也可能是由于預(yù)定時(shí)間已到。為找出wait()返回的真正原因,程序用當(dāng)前時(shí)間減開始時(shí)間(startTime),如差值大于預(yù)定時(shí)間則返回空值,否則再次調(diào)用getConnection()。
????把空閑的連接登記到連接池由240至250行的freeConnection()方法實(shí)現(xiàn),它的參數(shù)為返回給連接池的連接對(duì)象。該對(duì)象被加入到freeConnections向量的末尾,然后減少已使用連接計(jì)數(shù)。調(diào)用notifyAll()是為了通知其它正在等待可用連接的線程。
????許多Servlet引擎為實(shí)現(xiàn)安全關(guān)閉提供多種方法。數(shù)據(jù)庫連接池需要知道該事件以保證所有連接能夠正常關(guān)閉。DBConnectionManager類負(fù)協(xié)調(diào)整個(gè)關(guān)閉過程,但關(guān)閉連接池中所有連接的任務(wù)則由DBConnectionPool類負(fù)責(zé)。在307至323行實(shí)現(xiàn)的release()方法供DBConnectionManager調(diào)用。該方法遍歷freeConnections向量并關(guān)閉所有連接,然后從向量中刪除這些連接。
????
????
????四、類DBConnectionManager?說明
????
????該類只能創(chuàng)建一個(gè)實(shí)例,其它對(duì)象能夠調(diào)用其靜態(tài)方法(也稱為類方法)獲得該唯一實(shí)例的引用。如031至036行所示,DBConnectionManager類的建構(gòu)函數(shù)是私有的,這是為了避免其它對(duì)象創(chuàng)建該類的實(shí)例。
????DBConnectionManager類的客戶程序可以調(diào)用getInstance()方法獲得對(duì)該類唯一實(shí)例的引用。如018至029行所示,類的唯一實(shí)例在getInstance()方法第一次被調(diào)用期間創(chuàng)建,此后其引用就一直保存在靜態(tài)變量instance中。每次調(diào)用getInstance()都增加一個(gè)DBConnectionManager的客戶程序計(jì)數(shù)。即,該計(jì)數(shù)代表引用DBConnectionManager唯一實(shí)例的客戶程序總數(shù),它將被用于控制連接池的關(guān)閉操作。
????該類實(shí)例的初始化工作由146至168行之間的私有方法init()完成。其中?getResourceAsStream()方法用于定位并打開外部文件。外部文件的定位方法依賴于類裝載器的實(shí)現(xiàn)。標(biāo)準(zhǔn)的本地類裝載器查找操作總是開始于類文件所在路徑,也能夠搜索CLASSPATH中聲明的路徑。db.properties是一個(gè)屬性文件,它包含定義連接池的鍵-值對(duì)。可供定義的公用屬性如下:
??
????drivers?以空格分隔的JDBC驅(qū)動(dòng)程序類列表
????logfile?日志文件的絕對(duì)路徑
????
????其它的屬性和特定連接池相關(guān),其屬性名字前應(yīng)加上連接池名字:
????
????<?poolname>.url?數(shù)據(jù)庫的?JDBC?URL?
????<?poolname>.maxconn?允許建立的最大連接數(shù),0表示沒有限制?
????<?poolname>.user?用于該連接池的數(shù)據(jù)庫帳號(hào)
????<?poolname>.password?相應(yīng)的密碼
????
????其中url屬性是必需的,而其它屬性則是可選的。數(shù)據(jù)庫帳號(hào)和密碼必須合法。用于Windows平臺(tái)的db.properties文件示例如下:
????
????drivers=sun.jdbc.odbc.JdbcOdbcDriver?jdbc.idbDriver
????logfile=D:\\user\\src\\java\\DBConnectionManager\\log.txt
????
????idb.url=jdbc:idb:c:\\local\\javawebserver1.1\\db\\db.prp
????idb.maxconn=2
????
????access.url=jdbc:odbc:demo
????access.user=demo
????access.password=demopw
????
????注意在Windows路徑中的反斜杠必須輸入2個(gè),這是由于屬性文件中的反斜杠同時(shí)也是一個(gè)轉(zhuǎn)義字符。
????init()方法在創(chuàng)建屬性對(duì)象并讀取db.properties文件之后,就開始檢查logfile屬性。如果屬性文件中沒有指定日志文件,則默認(rèn)為當(dāng)前目錄下的DBConnectionManager.log文件。如日志文件無法使用,則向System.err輸出日志記錄。
????裝載和注冊(cè)所有在drivers屬性中指定的JDBC驅(qū)動(dòng)程序由170至192行之間的loadDrivers()方法實(shí)現(xiàn)。該方法先用StringTokenizer將drivers屬性值分割為對(duì)應(yīng)于驅(qū)動(dòng)程序名稱的字符串,然后依次裝載這些類并創(chuàng)建其實(shí)例,最后在?DriverManager中注冊(cè)該實(shí)例并把它加入到一個(gè)私有的向量drivers。向量drivers將用于關(guān)閉服務(wù)時(shí)從DriverManager取消所有JDBC?驅(qū)動(dòng)程序的注冊(cè)。
????init()方法的最后一個(gè)任務(wù)是調(diào)用私有方法createPools()創(chuàng)建連接池對(duì)象。如109至142行所示,createPools()方法先創(chuàng)建所有屬性名字的枚舉對(duì)象(即Enumeration對(duì)象,該對(duì)象可以想象為一個(gè)元素系列,逐次調(diào)用其nextElement()方法將順序返回各元素),然后在其中搜索名字以“.url”結(jié)尾的屬性。對(duì)于每一個(gè)符合條件的屬性,先提取其連接池名字部分,進(jìn)而讀取所有屬于該連接池的屬性,最后創(chuàng)建連接池對(duì)象并把它保存在實(shí)例變量pools中。散列表(Hashtable類?)pools實(shí)現(xiàn)連接池名字到連接池對(duì)象之間的映射,此處以連接池名字為鍵,連接池對(duì)象為值。
????為便于客戶程序從指定連接池獲得可用連接或?qū)⑦B接返回給連接池,類DBConnectionManager提供了方法getConnection()和freeConnection()。所有這些方法都要求在參數(shù)中指定連接池名字,具體的連接獲取或返回操作則調(diào)用對(duì)應(yīng)的連接池對(duì)象完成。它們的實(shí)現(xiàn)分別在051至064行、066至080行、038至049行。
????如082至107行所示,為實(shí)現(xiàn)連接池的安全關(guān)閉,DBConnectionManager提供了方法release()。在上面我們已經(jīng)提到,所有DBConnectionManager的客戶程序都應(yīng)該調(diào)用靜態(tài)方法getInstance()以獲得該管理器的引用,此調(diào)用將增加客戶程序計(jì)數(shù)。客戶程序在關(guān)閉時(shí)調(diào)用release()可以遞減該計(jì)數(shù)。當(dāng)最后一個(gè)客戶程序調(diào)用release(),遞減后的引用計(jì)數(shù)為0,就可以調(diào)用各個(gè)連接池的release()方法關(guān)閉所有連接了。管理類release()方法最后的任務(wù)是撤銷所有JDBC驅(qū)動(dòng)程序的注冊(cè)。
????
????
????五、Servlet使用連接池示例
????
????Servlet?API所定義的Servlet生命周期類如:
????
????1)?創(chuàng)建并初始化Servlet(init()方法)。
????2)?響應(yīng)客戶程序的服務(wù)請(qǐng)求(service()方法)。
????3)?Servlet終止運(yùn)行,釋放所有資源(destroy()方法)。
????
????本例演示連接池應(yīng)用,上述關(guān)鍵步驟中的相關(guān)操作為:
????
????1)?在init(),用實(shí)例變量connMgr?保存調(diào)用DBConnectionManager.getInstance()所返回的引用。
????2)?在service(),調(diào)用getConnection(),執(zhí)行數(shù)據(jù)庫操作,用freeConnection()將連接返回給連接池。
????3)?在destroy(),調(diào)用release()關(guān)閉所有連接,釋放所有資源。
????
????示例程序清單如下:
????
????import?java.io.*;
????import?java.sql.*;
????import?javax.servlet.*;
????import?javax.servlet.http.*;
????public?class?TestServlet?extends?HttpServlet?{
????private?DBConnectionManager?connMgr;
????
????public?void?init(ServletConfig?conf)?throws?ServletException?{
????super.init(conf);
????connMgr?=?DBConnectionManager.getInstance();
????}
????
????public?void?service(HttpServletRequest?req,?HttpServletResponse?res)?
????throws?IOException?{
????
????res.setContentType("text/html");
????PrintWriter?out?=?res.getWriter();
????Connection?con?=?connMgr.getConnection("idb");
????if?(con?==?null)?{
????out.println("不能獲取數(shù)據(jù)庫連接.");
????return;
????}
????ResultSet?rs?=?null;
????ResultSetMetaData?md?=?null;
????Statement?stmt?=?null;
????try?{
????stmt?=?con.createStatement();
????rs?=?stmt.executeQuery("SELECT?*?FROM?EMPLOYEE");
????md?=?rs.getMetaData();
????out.println("<?H1>職工數(shù)據(jù)<?/H1>");
????while?(rs.next())?{
????out.println("<?BR>");
????for?(int?i?=?1;?i?<?md.getColumnCount();?i++)?{
????out.print(rs.getString(i)?+?",?");
????}
????}
????stmt.close();
????rs.close();
????}
????catch?(SQLException?e)?{
????e.printStackTrace(out);
????}
????connMgr.freeConnection("idb",?con);
????}
????
????public?void?destroy()?{
????connMgr.release();
????super.destroy();
????}
????}?

轉(zhuǎn)載于:https://www.cnblogs.com/zhuor/archive/2005/11/07/270751.html

總結(jié)

以上是生活随笔為你收集整理的连结池详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。