仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 809|回复: 18
打印 上一主题 下一主题

[学习教程] JAVA编程:利用JAVA中的静态代办署理完成数据库毗连池...

[复制链接]
蒙在股里 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:39:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
在ruby里才是一切皆对象。当然我不并不是很了解ruby,但是ruby确实是将语法简化得很好。静态|数据|数据库|数据库毗连数据库毗连池在编写使用服务是常常必要用到的模块,太甚频仍的毗连数据库对服务功能来说是一个瓶颈,利用缓冲池手艺能够来打消这个瓶颈。我们能够在互联网上找到良多关于数据库毗连池的源程序,可是都发明如许一个配合的成绩:这些毗连池的完成办法都分歧水平地增添了与利用者之间的耦合度。良多的毗连池都请求用户经由过程其划定的办法猎取数据库的毗连,这一点我们能够了解,究竟今朝一切的使用服务器取数据库毗连的体例都是这类体例完成的。可是别的一个配合的成绩是,它们同时不同意利用者显式的挪用Connection.close()办法,而必要用其划定的一个办法来封闭毗连。这类做法有两个弱点:  第一:改动了用户利用习气,增添了用户的利用难度。
  起首我们来看看一个一般的数据库操纵历程:
intexecuteSQL(Stringsql)throwsSQLException
{
Connectionconn=getConnection();//经由过程某种体例猎取数据库毗连
PreparedStatementps=null;
intres=0;
try{
ps=conn.prepareStatement(sql);
res=ps.executeUpdate();
}finally{
try{
ps.close();
}catch(Exceptione){}
try{
conn.close();//
}catch(Exceptione){}
}
returnres;
}
  利用者在用完数据库毗连后一般是间接挪用毗连的办法close来开释数据库资本,假如用我们后面提到的毗连池的完成办法,那语句conn.close()将被某些特定的语句所替换。
  第二:使毗连池没法对当中的一切毗连举行独有把持。因为毗连池不同意用户间接挪用毗连的close办法,一旦利用者在利用的过程当中因为习气成绩间接封闭了数据库毗连,那末毗连池将没法一般保护一切毗连的形态,思索毗连池和使用由分歧开辟职员完成时这类成绩更简单呈现。
  综合下面提到的两个成绩,我们来会商一下怎样办理这两个要命的成绩。
  起首我们先设身处地的思索一下用户是想怎样来利用这个数据库毗连池的。用户能够经由过程特定的办法来猎取数据库的毗连,同时这个毗连的范例应当是尺度的java.sql.Connection。用户在猎取到这个数据库毗连后能够对这个毗连举行恣意的操纵,包含封闭毗连等。
  经由过程对用户利用的形貌,如何能够接受Connection.close办法就成了我们这篇文章的主题。
  为了接受数据库毗连的close办法,我们应当有一品种似于钩子的机制。比方在Windows编程中我们能够使用HookAPI来完成对某个WindowsAPI的接受。在JAVA中一样也有如许一个机制。JAVA供应了一个Proxy类和一个InvocationHandler,这两个类都在java.lang.reflect包中。我们先来看看SUN公司供应的文档是怎样形貌这两个类的。
publicinterfaceInvocationHandler

InvocationHandleristheinterfaceimplementedbytheinvocationhandlerofaproxyinstance.

Eachproxyinstancehasanassociatedinvocationhandler.
Whenamethodisinvokedonaproxyinstance,
themethodinvocationisencodedanddispatchedtotheinvokemethodofitsinvocationhandler.
  SUN的API文档中关于Proxy的形貌良多,这里就不排列出来。经由过程文档对接口InvocationHandler的形貌我们能够看到当挪用一个Proxy实例的办法时会触发Invocationhanlder的invoke办法。从JAVA的文档中我们也同时懂得到这类静态代办署理机制只能接受接口的办法,而对一样平常的类有效,思索到java.sql.Connection自己也是一个接口由此就找到懂得决怎样接受close办法的前途。
  起首,我们先界说一个数据库毗连池参数的类,界说了数据库的JDBC驱动程序类名,毗连的URL和用户名口令等等一些信息,该类是用于初始化毗连池的参数,详细界说以下:
publicclassConnectionParamimplementsSerializable
{
privateStringdriver;//数据库驱动程序
privateStringurl;//数据毗连的URL
privateStringuser;//数据库用户名
privateStringpassword;//数据库暗码
privateintminConnection=0;//初始化毗连数
privateintmaxConnection=50;//最年夜毗连数
privatelongtimeoutValue=600000;//毗连的最年夜余暇工夫
privatelongwaitTime=30000;//取毗连的时分假如没有可用毗连最年夜的守候工夫
  其次是毗连池的工场类ConnectionFactory,经由过程该类来将一个毗连池对象与一个称号对应起来,利用者经由过程该称号就能够猎取指定的毗连池对象,详细代码以下:
/**
*毗连池类厂,该类经常使用来保留多个数据源称号合数据库毗连池对应的哈希
*@authorliusoft
*/
publicclassConnectionFactory
{
//该哈希表用来保留数据源名和毗连池对象的干系表
staticHashtableconnectionPools=null;
static{
connectionPools=newHashtable(2,0.75F);
}
/**
*从毗连池工场中猎取指命名称对应的毗连池对象
*@paramdataSource毗连池对象对应的称号
*@returnDataSource前往称号对应的毗连池对象
*@throwsNameNotFoundException没法找到指定的毗连池
*/
publicstaticDataSourcelookup(StringdataSource)
throwsNameNotFoundException
{
Objectds=null;
ds=connectionPools.get(dataSource);
if(ds==null||!(dsinstanceofDataSource))
thrownewNameNotFoundException(dataSource);
return(DataSource)ds;
}

/**
*将指定的名字和数据库毗连设置绑定在一同并初始化数据库毗连池
*@paramname对应毗连池的称号
*@paramparam毗连池的设置参数,详细请见类ConnectionParam
*@returnDataSource假如绑定乐成后前往毗连池对象
*@throwsNameAlreadyBoundException必定名字name已绑定章抛出该非常
*@throwsClassNotFoundException没法找到毗连池的设置中的驱动程序类
*@throwsIllegalAccessException毗连池设置中的驱动程序类有误
*@throwsInstantiationException没法实例化驱动程序类
*@throwsSQLException没法一般毗连指定的数据库
*/
publicstaticDataSourcebind(Stringname,ConnectionParamparam)
throwsNameAlreadyBoundException,ClassNotFoundException,
IllegalAccessException,InstantiationException,SQLException
{
DataSourceImplsource=null;
try{
lookup(name);
thrownewNameAlreadyBoundException(name);
}catch(NameNotFoundExceptione){
source=newDataSourceImpl(param);
source.initConnection();
connectionPools.put(name,source);
}
returnsource;
}
/**
*从头绑定命据库毗连池
*@paramname对应毗连池的称号
*@paramparam毗连池的设置参数,详细请见类ConnectionParam
*@returnDataSource假如绑定乐成后前往毗连池对象
*@throwsNameAlreadyBoundException必定名字name已绑定章抛出该非常
*@throwsClassNotFoundException没法找到毗连池的设置中的驱动程序类
*@throwsIllegalAccessException毗连池设置中的驱动程序类有误
*@throwsInstantiationException没法实例化驱动程序类
*@throwsSQLException没法一般毗连指定的数据库
*/
publicstaticDataSourcerebind(Stringname,ConnectionParamparam)
throwsNameAlreadyBoundException,ClassNotFoundException,
IllegalAccessException,InstantiationException,SQLException
{
try{
unbind(name);
}catch(Exceptione){}
returnbind(name,param);
}
/**
*删除一个数据库毗连池对象
*@paramname
*@throwsNameNotFoundException
*/
publicstaticvoidunbind(Stringname)throwsNameNotFoundException
{
DataSourcedataSource=lookup(name);
if(dataSourceinstanceofDataSourceImpl){
DataSourceImpldsi=(DataSourceImpl)dataSource;
try{
dsi.stop();
dsi.close();
}catch(Exceptione){
}finally{
dsi=null;
}
}
connectionPools.remove(name);
}

}
  ConnectionFactory次要供应了用户将将毗连池绑定到一个详细的称号上和作废绑定的操纵。利用者只必要体贴这两个类便可利用数据库毗连池的功效。上面我们给出一段怎样利用毗连池的代码:
Stringname="pool";
Stringdriver="sun.jdbc.odbc.JdbcOdbcDriver";
Stringurl="jdbc:odbc:datasource";
ConnectionParamparam=newConnectionParam(driver,url,null,null);
param.setMinConnection(1);
param.setMaxConnection(5);
param.setTimeoutValue(20000);
ConnectionFactory.bind(name,param);
System.out.println("binddatasourceok.");
//以上代码是用来挂号一个毗连池对象,该操纵能够在程序初始化只做一次便可
//以下入手下手就是利用者真正必要写的代码
DataSourceds=ConnectionFactory.lookup(name);
try{
for(inti=0;i<10;i++){
Connectionconn=ds.getConnection();
try{
testSQL(conn,sql);
}finally{
try{
conn.close();
}catch(Exceptione){}
}
}
}catch(Exceptione){
e.printStackTrace();
}finally{
ConnectionFactory.unbind(name);
System.out.println("unbinddatasourceok.");
System.exit(0);
}
  从利用者的示例代码就能够看出,我们已办理了惯例毗连池发生的两个成绩。可是我们最最体贴的是怎样办理接受close办法的举措。接受事情次要在ConnectionFactory中的两句代码:
source=newDataSourceImpl(param);
source.initConnection();
  DataSourceImpl是一个完成了接口javax.sql.DataSource的类,该类保护着一个毗连池的对象。因为该类是一个受回护的类,因而它表露给利用者的办法只要接口DataSource中界说的办法,其他的一切办法对利用者来讲都是不成视的。我们先来体贴用户可会见的一个办法getConnection
/**
*@seejavax.sql.DataSource#getConnection(String,String)
*/
publicConnectiongetConnection(Stringuser,Stringpassword)throwsSQLException
{
//起首从毗连池中找出余暇的对象
Connectionconn=getFreeConnection(0);
if(conn==null){
//判别是不是凌驾最年夜毗连数,假如凌驾最年夜毗连数
//则守候必定工夫检察是不是有余暇毗连,不然抛出非常告知用户无可用毗连
if(getConnectionCount()>=connParam.getMaxConnection())
conn=getFreeConnection(connParam.getWaitTime());
else{//没有凌驾毗连数,从头猎取一个数据库的毗连
connParam.setUser(user);
connParam.setPassword(password);
Connectionconn2=DriverManager.getConnection(connParam.getUrl(),
user,password);
//代办署理将要前往的毗连对象
_Connection_conn=new_Connection(conn2,true);
synchronized(conns){
conns.add(_conn);
}
conn=_conn.getConnection();
}
}
returnconn;
}
/**
*从毗连池中取一个余暇的毗连
*@paramnTimeout假如该参数值为0则没有毗连时只是前往一个null
*不然的话守候nTimeout毫秒看是不是另有余暇毗连,假如没有抛出非常
*@returnConnection
*@throwsSQLException
*/
protectedsynchronizedConnectiongetFreeConnection(longnTimeout)
throwsSQLException
{
Connectionconn=null;
Iteratoriter=conns.iterator();
while(iter.hasNext()){
_Connection_conn=(_Connection)iter.next();
if(!_conn.isInUse()){
conn=_conn.getConnection();
_conn.setInUse(true);
break;
}
}
if(conn==null&&nTimeout>0){
//守候nTimeout毫秒以便看是不是有余暇毗连
try{
Thread.sleep(nTimeout);
}catch(Exceptione){}
conn=getFreeConnection(0);
if(conn==null)
thrownewSQLException("没有可用的数据库毗连");
}
returnconn;
}
  DataSourceImpl类中完成getConnection办法的跟一般的数据库毗连池的逻辑是分歧的,起首判别是不是有余暇的毗连,假如没有的话判别毗连数是不是已凌驾最年夜毗连数等等的一些逻辑。可是有一点分歧的是经由过程DriverManager失掉的数据库毗连并非实时前往的,而是经由过程一个叫_Connection的类中介一下,然后挪用_Connection.getConnection前往的。假如我们没有经由过程一其中介也就是JAVA中的Proxy来接受要前往的接口对象,那末我们就没有举措截住Connection.close办法。
  终究到了中心地点,我们先来看看_Connection是怎样完成的,然后再先容是客户端挪用Connection.close办法时走的是如何一个流程,为何并没有真实的封闭毗连。
/**
*数据毗连的自封装,屏障了close办法
*@authorLiudong
*/
class_ConnectionimplementsInvocationHandler
{
privatefinalstaticStringCLOSE_METHOD_NAME="close";
privateConnectionconn=null;
//数据库的忙形态
privatebooleaninUse=false;
//用户最初一次会见该毗连办法的工夫
privatelonglastAccessTime=System.currentTimeMillis();

_Connection(Connectionconn,booleaninUse){
this.conn=conn;
this.inUse=inUse;
}
/**
*Returnstheconn.
*@returnConnection
*/
publicConnectiongetConnection(){
//前往数据库毗连conn的接受类,以便截住close办法
Connectionconn2=(Connection)Proxy.newProxyInstance(
conn.getClass().getClassLoader(),
conn.getClass().getInterfaces(),this);
returnconn2;
}
/**
*该办法真实的封闭了数据库的毗连
*@throwsSQLException
*/
voidclose()throwsSQLException{
//因为类属性conn是没有被接受的毗连,因而一旦挪用close办法后就间接封闭毗连
conn.close();
}
/**
*ReturnstheinUse.
*@returnboolean
*/
publicbooleanisInUse(){
returninUse;
}

/**
*@seejava.lang.reflect.InvocationHandler#invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object)
*/
publicObjectinvoke(Objectproxy,Methodm,Object[]args)
throwsThrowable
{
Objectobj=null;
//判别是不是挪用了close的办法,假如挪用close办法则把毗连置为无用形态
if(CLOSE_METHOD_NAME.equals(m.getName()))
setInUse(false);
else
obj=m.invoke(conn,args);
//设置最初一次会见工夫,以便实时扫除超时的毗连
lastAccessTime=System.currentTimeMillis();
returnobj;
}

/**
*ReturnsthelastAccessTime.
*@returnlong
*/
publiclonggetLastAccessTime(){
returnlastAccessTime;
}

/**
*SetstheinUse.
*@paraminUseTheinUsetoset
*/
publicvoidsetInUse(booleaninUse){
this.inUse=inUse;
}
}
  一旦利用者挪用所失掉毗连的close办法,因为用户的毗连对象是经由接受后的对象,因而JAVA假造时机起首挪用_Connection.invoke办法,在该办法中起首判别是不是为close办法,假如不是则将代码转给真实的没有被接受的毗连对象conn。不然的话只是复杂的将该毗连的形态设置为可用。到此您大概就分明了全部接受的历程,可是同时也有一个疑问:如许的话是否是这些已创建的毗连就一直没有举措真正封闭?谜底是能够的。我们来看看ConnectionFactory.unbind办法,该办法起首找到名字对应的毗连池对象,然后封闭该毗连池中的一切毗连并删撤除毗连池。在DataSourceImpl类中界说了一个close办法用来封闭一切的毗连,具体代码以下:
/**
*封闭该毗连池中的一切数据库毗连
*@returnint前往被封闭毗连的个数
*@throwsSQLException
*/
publicintclose()throwsSQLException
{
intcc=0;
SQLExceptionexcp=null;
Iteratoriter=conns.iterator();
while(iter.hasNext()){
try{
((_Connection)iter.next()).close();
cc++;
}catch(Exceptione){
if(einstanceofSQLException)
excp=(SQLException)e;
}
}
if(excp!=null)
throwexcp;
returncc;
}
  该办法逐一挪用毗连池中每一个对象的close办法,这个close办法对应的是_Connection中对close的完成,在_Connection界说中封闭数据库毗连的时分是间接挪用没有经由接受的对象的封闭办法,因而该close办法真实的开释了数据库资本。
  以上笔墨只是形貌了接口办法的接受,详细一个有用的毗连池模块还必要对余暇毗连的监控并实时开释毗连。

而学习JAVA我觉得最应该避免的就是:只学习,不思考,只记忆,不实践!
爱飞 该用户已被删除
沙发
发表于 2015-1-21 12:23:39 来自手机 | 只看该作者
学Java必读的两个开源程序就是Jive和Pet Store.。 Jive是国外一个非常著名的BBS程序,完全开放源码。论坛的设计采用了很多先进的技术,如Cache、用户认证、Filter、XML等,而且论坛完全屏蔽了对数据库的访问,可以很轻易的在不同数据库中移植。论坛还有方便的安装和管理程序,这是我们平时编程时容易忽略的一部份(中国程序员一般只注重编程的技术含量,却完全不考虑用户的感受,这就是我们与国外软件的差距所在)。
小女巫 该用户已被删除
板凳
发表于 2015-1-21 12:23:39 | 只看该作者
其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。
冷月葬花魂 该用户已被删除
地板
发表于 2015-1-25 17:50:34 | 只看该作者
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
分手快乐 该用户已被删除
5#
发表于 2015-1-30 18:31:17 | 只看该作者
是一种将安全性(Security)列为第一优先考虑的语言
金色的骷髅 该用户已被删除
6#
发表于 2015-2-4 20:52:03 | 只看该作者
设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧
深爱那片海 该用户已被删除
7#
发表于 2015-2-6 17:24:36 | 只看该作者
应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项计划。随着1990年代互联网的发展
变相怪杰 该用户已被删除
8#
发表于 2015-2-17 16:12:39 | 只看该作者
在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。
灵魂腐蚀 该用户已被删除
9#
发表于 2015-2-23 02:38:40 | 只看该作者
是一种突破用户端机器环境和CPU
乐观 该用户已被删除
10#
发表于 2015-3-7 05:29:52 | 只看该作者
是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言
活着的死人 该用户已被删除
11#
发表于 2015-3-7 16:08:30 | 只看该作者
是一种将安全性(Security)列为第一优先考虑的语言
第二个灵魂 该用户已被删除
12#
发表于 2015-3-13 09:08:52 | 只看该作者
如果要向java web方向发展也要吧看看《Java web从入门到精通》学完再到《Struts2.0入门到精通》这样你差不多就把代码给学完了。有兴趣可以看一些设计模块和框架的包等等。
飘灵儿 该用户已被删除
13#
发表于 2015-3-20 16:38:43 | 只看该作者
其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。
因胸联盟 该用户已被删除
14#
发表于 2015-3-27 22:09:48 | 只看该作者
接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。
精灵巫婆 该用户已被删除
15#
发表于 2015-4-3 20:40:29 | 只看该作者
《JAVA语言程序设计》或《JAVA从入门到精通》这两本书开始学,等你编程有感觉的时候也可以回看一下。《JAVA读书笔记》这本书,因为讲的代码很多,也很容易看懂,涉及到面也到位。是你学习技术巩固的好书,学完后就看看《JAVA编程思想》这本书,找找一个自己写的代码跟书上的代码有什么不一样。
海妖 该用户已被删除
16#
发表于 2015-4-14 01:16:00 | 只看该作者
是一种使网页(Web Page)由静态(Static)转变为动态(Dynamic)的语言
若相依 该用户已被删除
17#
发表于 2015-4-27 03:16:07 | 只看该作者
你快去找一份Java的编程工作来做吧(如果是在校学生可以去做兼职啊),在实践中提高自己,那才是最快的。不过你得祈祷在公司里碰到一个高手,而且他 还愿意不厌其烦地教你,这样好象有点难哦!还有一个办法就是读开放源码的程序了。我们知道开放源码大都出自高手,他们设计合理,考虑周到,再加上有广大的程序员参与,代码的价值自然是字字珠叽,铿锵有力(对不起,偶最近《金装四大才子》看多了)。
老尸 该用户已被删除
18#
发表于 2015-4-27 04:40:21 | 只看该作者
学Java必读的两个开源程序就是Jive和Pet Store.。 Jive是国外一个非常著名的BBS程序,完全开放源码。论坛的设计采用了很多先进的技术,如Cache、用户认证、Filter、XML等,而且论坛完全屏蔽了对数据库的访问,可以很轻易的在不同数据库中移植。论坛还有方便的安装和管理程序,这是我们平时编程时容易忽略的一部份(中国程序员一般只注重编程的技术含量,却完全不考虑用户的感受,这就是我们与国外软件的差距所在)。
谁可相欹 该用户已被删除
19#
发表于 2015-5-1 14:12:02 | 只看该作者
我大二,Java也只学了一年,觉得还是看thinking in java好,有能力的话看英文原版(中文版翻的不怎么好),还能提高英文文档阅读能力。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-5-23 12:00

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表