天天看點

java servlet 連接配接池_用連接配接池提高Servlet通路資料庫的效率(轉載)

用連接配接池提高

Servlet

通路資料庫的效率(轉載)

Java Servlet

作為首選的伺服器端資料處理技術,正在迅速取代

CGI

腳本。

Servlet

超越

CGI

的優勢之一在于,不僅多個請求可以共享公用資源,而且還可以在不同使用者請求之間保留持續資料。本文介紹一種充分發揮該特色的實用技術,即資料庫連接配接池。

一、實作連接配接池的意義

動态

Web

站點往往用資料庫存儲的資訊生成

Web

頁面,每一個頁面請求導緻一次資料庫通路。連接配接資料庫不僅要開銷一定的通訊和記憶體資源,還必須完成使用者驗證、安全上下文配置這類任務,因而往往成為最為耗時的操作。當然,實際的連接配接時間開銷千變萬化,但

1

2

秒延遲并非不常見。如果某個基于資料庫的

Web

應用隻需建立一次初始連

接,不同頁面請求能夠共享同一連接配接,就能獲得顯著的性能改善。

Servlet

是一個

Java

類。

Servlet

引擎(它可能是

Web

服務軟體的一部分,也可能是一個獨立的附加子產品)在系統啟動或

Servlet

第一次被請求時将該類裝入

Java

虛拟機并建立它的一個執行個體。不同使用者請求由同一

Servlet

執行個體的多個獨立線程處理。那些要

求在不同請求之間持續有效的資料既可以用

Servlet

的執行個體變量來儲存,也可以儲存在獨立的輔助對象中。

JDBC

通路資料庫首先要建立與資料庫之間的連接配接,獲得一個連接配接對象(

Connection

),由連接配接對象提供執行

SQL

語句的方法。

本文介紹的資料庫連接配接池包括一個管理類

DBConnectionManager

,負責提供與多個連接配接池對象(

DBConnectionPool

類)之間的接口。每一個連接配接池對象管理一組

JDBC

連接配接對象,每一個連接配接對象可以被任意數量的

Servlet

共享。

DBConnectionPool

提供以下功能:

1)

從連接配接池擷取(或建立)可用連接配接。

2)

把連接配接傳回給連接配接池。

3)

在系統關閉時釋放所有資源,關閉所有連接配接。

此外,

DBConnectionPool

類還能夠處理無效連接配接(原來登記為可用的連接配接,由于某種原因不再可用,如逾時,通訊問題)

,并能夠限制連接配接池中的連接配接總數不超過某個預定值。

管理類

DBConnectionManager

用于管理多個連接配接池對象,它提供以下功能:

1)

裝載和注冊

JDBC

驅動程式。

2)

根據在屬性檔案中定義的屬性建立連接配接池對象。

3)

實作連接配接池名字與其執行個體之間的映射。

4)

跟蹤客戶程式對連接配接池的引用,保證在最後一個客戶程式結束時安全地關閉所有連接配接池。

本文餘下部分将詳細說明這兩個類,最後給出一個示例示範

Servlet

使用連接配接池的一般過程。

二、具體實作

DBConnectionManager.java

程式清單如下:

001 import java.io.*;

002 import java.sql.*;

003 import java.util.*;

004 import java.util.Date;

005

006

010 public class DBConnectionManager {

011 static private DBConnectionManager instance; //

唯一執行個體

012 static private int clients;

013

014 private Vector drivers = new Vector();

015 private PrintWriter log;

016 private Hashtable pools = new Hashtable();

017

018

023 static synchronized public DBConnectionManager getInstance() {

024 if (instance == null) {

025 instance = new DBConnectionManager();

026 }

027 clients++;

028 return instance;

029 }

030

031

034 private DBConnectionManager() {

035 init();

036 }

037

038

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

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

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

085 public synchronized void release() {

086 //

等待直到最後一個客戶程式調用

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

驅動程式

" + driver.getClass().getName()+"

的注冊

");

102 }

103 catch (SQLException e) {

104 log(e, "

無法撤銷下列

JDBC

驅動程式的注冊

: " + driver.getClass().getName());

105 }

106 }

107 }

108

109

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("

錯誤的最大連接配接數限制

: " + maxconn + " .

連接配接池

: " + poolName);

134 max = 0;

135 }

136 DBConnectionPool pool =

137 new DBConnectionPool(poolName, url, user, password, max);

138 pools.put(poolName, pool);

139 log("

成功建立連接配接池

" + poolName);

140 }

141 }

142 }

143

144

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 "

請確定

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

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("

成功注冊

JDBC

驅動程式

" + driverClassName);

186 }

187 catch (Exception e) {

188 log("

無法注冊

JDBC

驅動程式

: " +

189 driverClassName + ",

錯誤

: " + e);

190 }

191 }

192 }

193

194

197 private void log(String msg) {

198 log.println(new Date() + ": " + msg);

199 }

200

201

204 private void log(Throwable e, String msg) {

205 log.println(new Date() + ": " + msg);

206 e.printStackTrace(log);

207 }

208

209

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

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

245 public synchronized void freeConnection(Connection con) {

246 //

将指定連接配接加入到向量末尾

247 freeConnections.addElement(con);

248 checkedOut--;

249 notifyAll();

250 }

251

252

257 public synchronized Connection getConnection() {

258 Connection con = null;

259 if (freeConnections.size() > 0) {

260 //

擷取向量中第一個可用連接配接

261 con = (Connection) freeConnections.firstElement();

262 freeConnections.removeElementAt(0);

263 try {

264 if (con.isClosed()) {

265 log("

從連接配接池

" + name+"

删除一個無效連接配接

");

266 //

遞歸調用自己

,

嘗試再次擷取可用連接配接

267 con = getConnection();

268 }

269 }

270 catch (SQLException e) {

271 log("

從連接配接池

" + name+"

删除一個無效連接配接

");

272 //

遞歸調用自己

,

嘗試再次擷取可用連接配接

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

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()

傳回的原因是逾時

301 return null;

302 }

303 }

304 return con;

305 }

306

307

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("

關閉連接配接池

" + name+"

中的一個連接配接

");

317 }

318 catch (SQLException e) {

319 log(e, "

無法關閉連接配接池

" + name+"

中的連接配接

");

320 }

321 }

322 freeConnections.removeAllElements();

323 }

324

325

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+"

建立一個新的連接配接

");

338 }

339 catch (SQLException e) {

340 log(e, "

無法建立下列

URL

的連接配接

: " + URL);

341 return null;

342 }

343 return con;

344 }

345 }

346 }

轉自:動态網制作指南

www.knowsky.com

|----------------------------------------------------------------------------------------|

版權聲明  版權所有 @zhyiwww

引用請注明來源 http://www.blogjava.net/zhyiwww

|----------------------------------------------------------------------------------------|

posted on 2006-06-02 19:08 zhyiwww 閱讀(293) 評論(0)  編輯  收藏 所屬分類: j2ee