用连接池提高Servlet访问数据库的效率.docx

上传人:b****8 文档编号:30477289 上传时间:2023-08-15 格式:DOCX 页数:17 大小:24.54KB
下载 相关 举报
用连接池提高Servlet访问数据库的效率.docx_第1页
第1页 / 共17页
用连接池提高Servlet访问数据库的效率.docx_第2页
第2页 / 共17页
用连接池提高Servlet访问数据库的效率.docx_第3页
第3页 / 共17页
用连接池提高Servlet访问数据库的效率.docx_第4页
第4页 / 共17页
用连接池提高Servlet访问数据库的效率.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

用连接池提高Servlet访问数据库的效率.docx

《用连接池提高Servlet访问数据库的效率.docx》由会员分享,可在线阅读,更多相关《用连接池提高Servlet访问数据库的效率.docx(17页珍藏版)》请在冰豆网上搜索。

用连接池提高Servlet访问数据库的效率.docx

用连接池提高Servlet访问数据库的效率

∙用连接池提高Servlet访问数据库的效率-JSP教程、数据库相关

∙来源:

作者:

发布时间:

2007-12-2714:

03:

11

javaservlet作为最佳选择的服务器端数据处理技术,正在迅速取代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程式清单如下:

001importjava.io.*;

002importjava.sql.*;

003importjava.util.*;

004importjava.util.date;

005

006/**

007*管理类dbconnectionmanager支持对一个或多个由属性文件定义的数据库连接

008*池的访问.客户程式能调用getinstance()方法访问本类的唯一实例.

009*/

010publicclassdbconnectionmanager{

011staticprivatedbconnectionmanagerinstance;//唯一实例

012staticprivateintclients;

013

014privatevectordrivers=newvector();

015privateprintwriterlog;

016privatehashtablepools=newhashtable();

017

018/**

019*返回唯一实例.如果是第一次调用此方法,则创建实例

020*

021*@returndbconnectionmanager唯一实例

022*/

023staticsynchronizedpublicdbconnectionmanagergetinstance(){

024if(instance==null){

025instance=newdbconnectionmanager();

026}

027clients++;

028returninstance;

029}

030

031/**

032*建构函数私有以防止其他对象创建本类实例

033*/

034privatedbconnectionmanager(){

035init();

036}

037

038/**

039*将连接对象返回给由名字指定的连接池

040*

041*@paramname在属性文件中定义的连接池名字

042*@paramcon连接对象

043*/

044publicvoidfreeconnection(stringname,connectioncon){

045dbconnectionpoolpool=(dbconnectionpool)pools.get(name);

046if(pool!

=null){

047pool.freeconnection(con);

048}

049}

050

051/**

052*获得一个可用的(空闲的)连接.如果没有可用连接,且已有连接数小于最大连接数

053*限制,则创建并返回新连接

054*

055*@paramname在属性文件中定义的连接池名字

056*@returnconnection可用连接或null

057*/

058publicconnectiongetconnection(stringname){

059dbconnectionpoolpool=(dbconnectionpool)pools.get(name);

060if(pool!

=null){

061returnpool.getconnection();

062}

063returnnull;

064}

065

066/**

067*获得一个可用连接.若没有可用连接,且已有连接数小于最大连接数限制,

068*则创建并返回新连接.否则,在指定的时间内等待其他线程释放连接.

069*

070*@paramname连接池名字

071*@paramtime以毫秒计的等待时间

072*@returnconnection可用连接或null

073*/

074publicconnectiongetconnection(stringname,longtime){

075dbconnectionpoolpool=(dbconnectionpool)pools.get(name);

076if(pool!

=null){

077returnpool.getconnection(time);

078}

079returnnull;

080}

081

082/**

083*关闭所有连接,撤销驱动程式的注册

084*/

085publicsynchronizedvoidrelease(){

086//等待直到最后一个客户程式调用

087if(--clients!

=0){

088return;

089}

090

091enumerationallpools=pools.elements();

092while(allpools.hasmoreelements()){

093dbconnectionpoolpool=(dbconnectionpool)allpools.nextelement();

094pool.release();

095}

096enumerationalldrivers=drivers.elements();

097while(alldrivers.hasmoreelements()){

098driverdriver=(driver)alldrivers.nextelement();

099try{

100drivermanager.deregisterdriver(driver);

101log("撤销jdbc驱动程式"+driver.getclass().getname()+"的注册");

102}

103catch(sqlexceptione){

104log(e,"无法撤销下列jdbc驱动程式的注册:

"+driver.getclass().getname());

105}

106}

107}

108

109/**

110*根据指定属性创建连接池实例.

111*

112*@paramprops连接池属性

113*/

114privatevoidcreatepools(propertiesprops){

115enumerationpropnames=props.propertynames();

116while(propnames.hasmoreelements()){

117stringname=(string)propnames.nextelement();

118if(name.endswith(".url")){

119stringpoolname=name.substring(0,name.lastindexof("."));

120stringurl=props.getproperty(poolname+".url");

121if(url==null){

122log("没有为连接池"+poolname+"指定url");

123continue;

124}

125stringuser=props.getproperty(poolname+".user");

126stringpassword=props.getproperty(poolname+".password");

127stringmaxconn=props.getproperty(poolname+".maxconn","0");

128intmax;

129try{

130max=integer.valueof(maxconn).intvalue();

131}

132catch(numberformatexceptione){

133log("错误的最大连接数限制:

"+maxconn+".连接池:

"+poolname);

134max=0;

135}

136dbconnectionpoolpool=

137newdbconnectionpool(poolname,url,user,password,max);

138pools.put(poolname,pool);

139log("成功创建连接池"+poolname);

140}

141}

142}

143

144/**

145*读取属性完成初始化

146*/

147privatevoidinit(){

148inputstreamis=getclass().getresourceasstream("/db.properties");

149propertiesdbprops=newproperties();

150try{

151dbprops.load(is);

152}

153catch(exceptione){

154system.err.println("不能读取属性文件."+

155"请确保db.properties在classpath指定的路径中");

156return;

157}

158stringlogfile=dbprops.getproperty("logfile","dbconnectionmanager.log");

159try{

160log=newprintwriter(newfilewriter(logfile,true),true);

161}

162catch(ioexceptione){

163system.err.println("无法打开日志文件:

"+logfile);

164log=newprintwriter(system.err);

165}

166loaddrivers(dbprops);

167createpools(dbprops);

168}

169

170/**

171*装载和注册所有jdbc驱动程式

172*

173*@paramprops属性

174*/

175privatevoidloaddrivers(propertiesprops){

176stringdriverclasses=props.getproperty("drivers");

177stringtokenizerst=newstringtokenizer(driverclasses);

178while(st.hasmoreelements()){

179stringdriverclassname=st.nexttoken().trim();

180try{

181driverdriver=(driver)

182class.forname(driverclassname).newinstance();

183drivermanager.registerdriver(driver);

184drivers.addelement(driver);

185log("成功注册jdbc驱动程式"+driverclassname);

186}

187catch(exceptione){

188log("无法注册jdbc驱动程式:

"+

189driverclassname+",错误:

"+e);

190}

191}

192}

193

194/**

195*将文本信息写入日志文件

196*/

197privatevoidlog(stringmsg){

198log.println(newdate()+":

"+msg);

199}

200

201/**

202*将文本信息和异常写入日志文件

203*/

204privatevoidlog(throwablee,stringmsg){

205log.println(newdate()+":

"+msg);

206e.printstacktrace(log);

207}

208

209/**

210*此内部类定义了一个连接池.他能够根据需求创建新连接,直到预定的最

211*大连接数为止.在返回连接给客户程式之前,他能够验证连接的有效性.

212*/

213classdbconnectionpool{

214privateintcheckedout;

215privatevectorfreeconnections=newvector();

216privateintmaxconn;

217privatestringname;

218privatestringpassword;

219privatestringurl;

220privatestringuser;

221

222/**

223*创建新的连接池

224*

225*@paramname连接池名字

226*@paramurl数据库的jdbcurl

227*@paramuser数据库帐号,或null

228*@parampassword密码,或null

229*@parammaxconn此连接池允许建立的最大连接数

230*/

231publicdbconnectionpool(stringname,stringurl,stringuser,stringpassword,

232intmaxconn){

233this.name=name;

234this.url=url;

235this.user=user;

236this.password=password;

237this.maxconn=maxconn;

238}

239

240/**

241*将不再使用的连接返回给连接池

242*

243*@paramcon客户程式释放的连接

244*/

245publicsynchronizedvoidfreeconnection(connectioncon){

246//将指定连接加入到向量末尾

247freeconnections.addelement(con);

248checkedout--;

249notifyall();

250}

251

252/**

253*从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接

254*数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,

255*然后递归调用自己以尝试新的可用连接.

256*/

257publicsynchronizedconnectiongetconnection(){

258connectioncon=null;

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

260//获取向量中第一个可用连接

261con=(connection)freeconnections.firstelement();

262freeconnections.removeelementat(0);

263try{

264if(con.isclosed()){

265log("从连接池"+name+"删除一个无效连接");

266//递归调用自己,尝试再次获取可用连接

267con=getconnection();

268}

269}

270catch(sqlexceptione){

271log("从连接池"+name+"删除一个无效连接");

272//递归调用自己,尝试再次获取可用连接

273con=getconnection();

274}

275}

276elseif(maxconn==0||checkedout

277con=newconnection();

278}

279if(con!

=null){

280checkedout++;

281}

282returncon;

283}

284

285/**

286*从连接池获取可用连接.能指定客户程式能够等待的最长时间

287*参见前一个getconnection()方法.

288*

289*@paramtimeout以毫秒计的等待时间限制

290*/

291publicsynchronizedconnectiongetconnection(longtimeout){

292longstarttime=newdate().gettime();

293connectioncon;

294while((con=getconnection())==null){

295try{

296wait(timeout);

297}

298catch(interruptedexceptione){}

299if((newdate().gettime()-starttime)>=timeout){

300//wait()返回的原因是超时

301returnnull;

302}

303}

304returncon;

305}

306

307/**

308*关闭所有连接

309*/

310publicsynchronizedvoidrelease(){

311enumerationallconnections=freeconnections.elements();

312while(allconnections.hasmoreelements()){

313connectioncon=(connection)allconnections.nextelement();

314try{

315con.close();

316log("关闭连接池"+name+"中的一个连接");

317}

318catch(sqlexceptione){

319log(e,"无法关闭连接池"+name+"中的连接");

320}

321}

322freeconnections.removeallelements();

323}

324

325/**

326*创建新的连接

327*/

328privateconnectionnewconnection(){

329connectioncon=null;

330try{

331if(user==null){

332

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 政史地

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1