仓酷云

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

[学习教程] JAVA网页编程之利用Annotations计划一个MVC框架

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

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

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

x
不得不提一下的是:.net是看到java红,而开发出来的工具。计划  当计划一个使用程序时,明晰的分别该程序的分歧逻辑组件,老是被证实是无益的.同时也存在很多分歧的形式来匡助开辟者完成这个方针。个中最着名同时也最经常使用的天然是Model-View-Controller(MVC)了,它可以将每一个使用程序(大概使用程序的一部分)分红三个分歧功效的组件,而且界说了把他们联合在一同的划定规矩。Swing自己就是基于这个形式的,并且每一个利用Struts,这个盛行的开辟Web使用框架的人也都懂得埋没在MVC前面的实际.

  这篇文章先容了怎样经由过程利用annotation而增添一个新的组件来增强MVC,使其可以加倍便利地往失落models跟views之间的耦合。这篇文章先容了一个叫Stamps的开源库,它是基于MVC组件之上的,但它往除一切在开辟MVC时所需的,在models,views和controllers之间创建接洽的包袱。

基本常识:MVC和annotations

  正如MVC这个名字所指出的,Model-View-Controller形式倡议将一个使用程序分红以下三个组件:
・Model:包括了数据模子和一切用来断定使用程序形态的信息。它一样平常来讲是有层次的而且自力于其他组件的。
・View:从分歧于model的角度动身,它界说了存储在模子中数据的展示体例。它一般被以为是你的使用程序的用户界面(大概GUI),大概以Web使用为例,场景就是你经由过程扫瞄器看到的页面。
・Controller:它代表使用程序的逻辑部分。在这里,它界说了一个用户怎样和使用程序举行交互而且也界说了用户举动是怎样映照到model的改动。

  这些组件严密的接洽在一同:用户影响view,反过去view关照controller来更新model.终极model又更新view来反应它的新形态。就展示了这类典范的MVC布局。


.一个典范的MVC布局

  作为J2SE5.0所供应的一个新的功效,annotations同意开辟者往classes,methods,fields,和其他程序元素中增添元数据。就像反射机制一样,以后良多使用程序为了某些缘故原由能在运转时代猎取并利用那些元数据。由于J2SE5.0只是界说了怎样编写和读取annotations,并没有申明在那里利用他们(象@Override如许的用于提早界说的破例),开辟者具有无量多的在很多分歧场所利用他们的大概性:文档编写,与对象相干的映照,代码天生,等等..Annotations已变的非常盛行,以致于年夜多半框架和库都更新本人来撑持他们。至于更多的关于MVC和annotations的信息请拜见资本。

超出MVC:dispatcher

  就像前文提到的一样,models和views之间的一些耦合是需要的由于后者必需反应前者的形态。一般Java程序利用间接或直接的耦合将组件绑定在一同。间接耦合产生在当view和model之间有一个间接相干的时分,model包括一列必要保持的views。直接耦合一般产生在一个基于事务分拨的机制中。Model会在它形态改动时引发事务,同时一些自力的views会将他们本人注册成事务侦听器。

  一般我们对照喜爱直接耦合由于它使model完整不晓得view的存在,相反view必需和model坚持必定的接洽从而将本人注册到model上。在这篇文章里我将先容的框架就是利用直接耦合,可是为了更好的下降组件之间的耦合,view必需不晓得model的存在;也就是说,model和view没有被绑定在一同。

  为了完成这个方针,我已界说了一个新的组件,就是dispatcher,它能作为一个存在于views和models之间的分别层。它能处置models和views两边之间的注册而且分拨由model引发的事务到注册的views上。它利用java.beans.PropertyChangeEvent对象来体现由model传送到view的事务;但是,这个框架的计划是充足开放的,它能够撑持分歧事务范例的完成。

  办理注册的views列表的包袱因而就从model上移开了,同时,由于view只和这个自力于使用程序的dispatcher有关,view不晓得model的存在。假如你熟习Struts外部,你大概可以看出Struts的controller就是在实行如许一个义务,它将Actions和他们联系关系的JSP(JavaServerPages)体现页面接洽在一同。

  如今,我们所计划的MVC框架就像所形貌的一样。Dispatcher在个中承当了一个于controller相当的脚色。


.具有分外dispatcher组件的改善的MVC框架

  因为dispatcher必需是自力于使用程序的,以是必需界说一些通用的联合models和views的标准。我们将利用annotations来完成这类联合,它将会被用来标注views而且断定哪一个view是受哪一个model的影响的,及这类影响是怎样的。经由过程这类体例,annotations就像是贴在明信片上的邮票一样,驱动dispatcher来实行传送model事务的义务(这就是这一框架名字的由来)。


使用实例

  我们将利用一个复杂的计秒器使用程序做该框架的一个使用实例:它同意用户设置工夫周期来记数和启动/中断这个准时器。一旦已往划定的工夫,用户将会被扣问是不是作废大概重启这个准时器。这个使用程序的完整源代码能够从项目主页上找到。


.一个复杂的使用程序

  这个modle长短常复杂的,它只存储两个属性:周期和已已往的秒数。注重当它个中一个属性产生变更时它是怎样利用java.beans.PropertyChangeSuppor来引发事务。
publicclassTimeModel{

publicstaticfinalintDEFAULT_PERIOD=60;

privateTimertimer;
privatebooleanrunning;

privateintperiod;
privateintseconds;

privatePropertyChangeSupportpropSupport;

/**
*Gettersandsettersformodelproperties.
*/

/**
*Returnsthenumberofcountedseconds.
*
*@returnthenumberofcountedseconds.
*/
publicintgetSeconds(){
returnseconds;
}

/**
*Setsthenumberofcountedseconds.propSupportisaninstanceofPropertyChangeSupport
*usedtodispatchmodelstatechangeevents.
*
*@paramsecondsthenumberofcountedseconds.
*/
publicvoidsetSeconds(intseconds){
propSupport.firePropertyChange("seconds",this.seconds,seconds);
this.seconds=seconds;
}

/**
*Setstheperiodthatthetimerwillcount.propSupportisaninstanceofPropertyChangeSupport
*usedtodispatchmodelstatechangeevents.
*
*@paramperiodtheperiodthatthetimerwillcount.
*/
publicvoidsetPeriod(Integerperiod){
propSupport.firePropertyChange("period",this.period,period);
this.period=period;
}

/**
*Returnstheperiodthatthetimerwillcount.
*
*@returntheperiodthatthetimerwillcount.
*/
publicintgetPeriod(){
returnperiod;
}

/**
*Decidesifthetimermustrestart,dependingontheuseranswer.Thismethod
*isinvokedbythecontrolleroncetheviewhasbeennotifiedthatthetimerhas
*countedallthesecondsdefinedintheperiod.
*
*@paramanswertheuseranswer.
*/
publicvoidquestionAnswer(booleananswer){
if(answer){
timer=newTimer();
timer.schedule(newSecondsTask(this),1000,1000);
running=true;
}
}

/**
*Starts/stopthetimer.Thismethodisinvokedbythecontrolleronuserinput.
*/
publicvoidsetTimer(){
if(running){
timer.cancel();
timer.purge();
}
else{
setSeconds(0);
timer=newTimer();
timer.schedule(newSecondsTask(this),1000,1000);
}

running=!running;
}

/**
*Thetaskthatcountstheseconds.
*/
privateclassSecondsTaskextendsTimerTask{

/**
*WerenotinterestedintheimplementationsoIomitit.
*/

}
}


  Controller只界说了用户能够实行的而且可以从以下接口笼统出来的actions。

publicinterfaceTimeController{

/**
*Actioninvokedwhentheuserwantstostart/stopthetimer
*/
voiduserStartStopTimer();

/**
*Actioninvokedwhentheuserwantstorestartthetimer
*/
voiduserRestartTimer();

/**
*Actioninvokedwhentheuserwantstomodifythetimerperiod
*
*@paramnewPeriodthenewperiod
*/
voiduserModifyPeriod(IntegernewPeriod);
}


  你可使用你本人喜好的GUI编纂器来画这个view。出于我们本身的情形,我们只必要几个大众的methods就能够供应充足的功效来更新view的fields,以下面的这个例子所示:

/**
*UpdatestheGUIsecondsfields
*/
publicvoidsetScnFld(Integersec){
//scnFldisaSwingtextfield
SwingUtilities.invokeLater(newRunnable(){
publicvoidrun(){
scnFld.setText(sec.toString());
}
});
}


  在这里我们注重到我们正在利用POJOs(plain-oldJavaobjects),同时我们不必恪守任何编码习气大概完成特定的接口(事务引发代码除外)。剩下的就只要界说组件之间的绑定了。

事务分拨annotations

  绑定机制的中心就是@ModelDependentannotation的界说:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public@interfaceModelDependent{

StringmodelKey()default"";

StringpropertyKey()default"";

booleanruntimeModel()defaultfalse;

booleanruntimeProperty()defaultfalse;

}


  这个annotation能被用在view的methods上,同时dispatcher也会利用这些供应的参数(即modelKey和propertyKey)来断定这个view将会呼应的model事务。这个view既利用modelKey参数来指定它感乐趣的可使用的models又利用propertyKey参数来婚配分派的java.beans.PropertyChangeEvents的属性称号。

  ViewmethodsetScnFld()因而被标注以下信息(这里,timeModel供应了用来将model注册到dispatcher上的key):

/**
*UpdatestheGUIsecondsfields
*/
@ModelDependent(modelKey="timeModel",propertyKey="seconds")
publicvoidsetScnFld(finalIntegersec){
//scnFldisaSwingtextfield
SwingUtilities.invokeLater(newRunnable(){
publicvoidrun(){
scnFld.setText(sec.toString());
}
});
}


  因为dispatcher既晓得model引发的事务又晓得事务自己-比方,它晓得联系关系的modelKey和propertyKey-这是独一必要用来绑定views和models的信息。Model和view乃至不必要分享通讯接口大概共用的数据库。

  借助我们会商的绑定机制,我们能够容易的改动潜伏的view而不改动其他任何工具。上面的代码是依照利用SWT(StandardWidgetToolkit)而不是Swing完成的统一个method:

@ModelDependent(modelKey="timeModel",propertyKey="seconds")
publicvoidsetScnFld(finalIntegersec){
Display.getDefault().asyncExec(newRunnable(){
publicvoidrun(){
secondsField.setText(sec.toString());
}
});
}


  一个完整没有耦合的体系存在以下长处:View能够加倍简单地顺应model地改动,只管model一般都是不乱地,相反view是常常被改动。加上体系能够经由过程利用GUI编纂器大概其他源码天生器来计划,制止了将天生地代码与model-view通讯代码夹杂在一同。又因为model-view的绑定信息是和源码联系关系的元数据,因而也绝对简单把它使用到IDE天生的GUIs大概将已存在的使用程序转化成这个框架。加上具有独自的基本代码,view和model能够被看成是自力组件来开辟,这极可能简化了使用程序的开辟历程。组件测试也能够被简化,由于每一个组件能够被独自地测试,而且出于调试的目标,我们能够用假的model和view来取代实在的组件。

  但是,这里也存在很多弱点。由于如今当利用接口和大众的classes来绑定model和view时,我们不克不及再供应编译时代的平安性了,大概呈现的打字毛病将招致组件之间一个绑定的漏掉,从而招致呈现运转时代的毛病。

  经由过程利用@ModelDependent的会商过的modelKey和propertyKey元素,你能够界说model和view之间静态的接洽。但是,实际天下的使用程序证实view必需可以常常静态的顺应变更的models和使用程序的形态:思索到用户界面的分歧部分可以在使用程序的性命周期内被制造和删除。因而我将先容怎样利用这个框架与其他经常使用手艺一同来处置此类情况。

静态MVC绑定

  关于那些依附XML绑定(大概其他一些基于设置文件的声明性绑定)的框架,存在一个成绩那就是静态绑定例则。在这些框架下,静态变更是不成能的,因而一般开辟者决意每次将冗余的绑定信息与一些利用准确绑定的判断算法耦合在一同。

  为了奇妙的办理这个成绩,Stamps框架供应了两种体例在运转时代改动绑定。第一种体例是,views和models能够接纳事务监听器与GUI窗口小部件团结的体例在dispatcher上注册和刊出。如许同意特定的views只在必要他们的时分被关照到。比方,一个与使用程序有接洽的监督把持台能够只在用户哀求的时分与被它监督的对象绑定在一同。

  第二种体例是使用@ModelDependentannotation供应的两个元素runtimeModel()和runtimeProperty()。他们指了然某个断定的model和它的分派事务会在运转时代被断定。假如这两个设定中有一个是准确的,那末各自的key(modelKey或propertyKey)会在view上被method挪用来失掉必要利用的值。比方:一个卖力显现一组新channels(每一个channel就是一个model)的view,它就依附于用户的输出来断定必要绑定的channel。

这类情况的实比方下:

//Thismethodisinvokedtodisplayallthemessagesofonenewschannel
@ModelDependent(modelKey="dynamicChannel",propertyKey="allmessages",runtimeModel=true)
publicvoidsetAllMessages(java.util.Listmessages){
//Updatestheuserinterface
}

publicStringgetDynamicChannel(){
//Returnsthechannelrequestedbytheuser
}


附加的annotations

  因为天下其实不完善,一些附加的annotations被界说来匡助办理实际天下的案例。@Namespace同意开辟者为了更好的办理modeldomain将其再细分红分歧的部分。因为独自一个dispatcher能够处置多个models,modelkeys中将呈现的抵触。因而,它能将成群的models和相干的views分到分歧的但同属一个namespace下的domains中往,如许一来,他们就不会搅扰对方。

  @Transformannotation供应了on-the-fly对象转化,从包括在model事务中的对象到被receivingviews承受的对象的。因此,这个框架就能够顺应已存的代码而不必要做任何的修改。这个annotation承受一个注册在无效转化上的单一参数(被界说成一个特别接口的完成)。

  @Refreshableannotation能经由过程标注model的属性来撑持后面会商的静态毗连和分别views。利用这个annotation,该框架能够处置静态和静态的MVC结构,在分歧的工夫把分歧的views绑定到model上。

  要了解@Refreshable的利用,我们必需回到之前的谁人监控把持台的例子。这个把持台(用MVC的术语来讲就是一个view)能够静态地绑定和分开model,取决于用户的必要。当把持器毗连到model的时分@Refreshableannotation能够被用来让这个把持器随时懂得其model的形态。当一个view毗连到这个框架时,它必需在以后model的形态下被更新。因而,dispatcher扫描model寻觅@Refreshableannotations而且天生与view它自己从model一般承受到的不异的事务。这些事务接着被之前会商过的绑定机制分拨。

散布式MVC收集

  Dispatcher有一个很重的包袱那就是它卖力处置事务的传送周期中一切重型信息的传送:
・Model引发一个事务用来断定它已履历过的一些改动,dispatcher处置关照model.
・Dispatcher扫描一切注册在它那边的views,寻觅@ModelDependentannotations,这些annotations明白了views但愿关照的改动及当每一个model事务产生时,必要在views上挪用的method.
・假如必要,转化将会被用于事务数据上.
・viewmethod在被挪用时会从被引发的事务里抽取参数,接着view会更新本人.

  从另外一个方面来说,当一个新view在dispatcher上注册时:
・View告知dispatcher有关modelKey的信息,modelkey能断定它将被毗连到哪个model上(该model的事务将卖力组装view)
・假如必要,dispatcher扫描model寻觅@Refreshableannotations并利用他们来临盆将要实时更新view假的model事务
・这些事务将经由过程利用上述的按次被分拨,接着view被更新.

  一切这些既不触及view也不触及model的事情,他们站在他们各自的信息通讯渠道的两头.无所谓这些信息是在一个当地JVM外部传输仍是在多个远程主机上的JVM之间传输.假如想将当地使用程序转化成Client/Server使用程序所需的只是复杂地改动dispatcher内里的逻辑,而model和view都不会受影响.下图就是一个示例:


.一个基于散布式网路创建的MVC,点击缩略图检察全图

  如上图所示,单一的dispatcher被一个与model处在统一个host上的transmitter(it.battlehorse.stamps.impl.BroadcastDispatcher的一个instance)和一个(或多个)与view处在统一个host上的receiver(it.battlehorse.stamps.impl.FunnelDispatcher)所代替.Stamps框架默许的完成利用了一个创立于JGroups上的动静传送层,JGroups是一个牢靠的多点传送通讯的工具包,象收集传输机制(可是分歧的完成和利用)一样事情.经由过程利用它能够取得一个不乱牢靠的,多协定的,失利警悟的通讯.

  对我们使用程序(dispatcher)开端创建的一个改动,使我们从一个单一用户界面的自力运转的使用程序转移到一个多用户散布式的使用程序.当model进进或分开这个收集(设想一个通讯失利)的时分,框架能够关照有数的监听接口,因而远程views能够接纳得当的呼应.比方,显现一个告诫信息给用户.这个框架也能够供应有效的methods来匡助将当地的controllers转化成远程的.

总结和择要

  仍有很多元素必要被探究,就像计划controllers的体例一样,它在今朝和dispatchers具有分歧的广泛性.该框架假定一般的controller-model绑定,因为前者必要晓得怎样往驱动后者.将来的开辟偏向将是撑持分歧范例的views,比方利用一个Web扫瞄器,收集警悟的applets,和Java与JavaScript的通讯.

  已会商的Stamps库申明怎样在一个MVC架构中下降views和models之间的耦合和这个框架能够无效的使用Javaannotations将绑定信息从实践开辟程序组件分别开.具有断绝的绑定逻辑同意你在物理大将元件分别开而且能供应一个当地和一个client/server布局而不必要改动使用逻辑大概暗示层.这些方针供应对由一个象MVC一样坚实的计划形式与由annotations供应的功效壮大的元数据分离在一同所供应的大概性的洞察.

你通过从书的数量和开发周期及运行速度来证明:net和ruby要比java简单。
精灵巫婆 该用户已被删除
沙发
发表于 2015-1-20 17:29:37 | 只看该作者
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
活着的死人 该用户已被删除
板凳
发表于 2015-1-24 17:36:31 | 只看该作者
应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项计划。随着1990年代互联网的发展
admin 该用户已被删除
地板
发表于 2015-2-2 11:24:52 | 只看该作者
你一定会高兴地说,哈哈,原来成为Java高手就这么简单啊!记得Tomjava也曾碰到过一个项目经理,号称Java很简单,只要三个月就可以学会。
透明 该用户已被删除
5#
发表于 2015-2-4 10:43:15 | 只看该作者
Java是一个纯的面向对象的程序设计语言,它继承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)
飘飘悠悠 该用户已被删除
6#
发表于 2015-2-6 09:52:21 | 只看该作者
你就该学一学Servlet了。Servlet就是服务器端小程序,他负责生成发送给客户端的HTML文件。JSP在执行时,也是先转换成Servlet再运行的。虽说JSP理论上可以完全取代Servlet,这也是SUN推出JSP的本意,可是Servlet用来控制流程跳转还是挺方便的,也令程序更清晰。接下来你应该学习一下Javabean了,可能你早就看不管JSP在HTML中嵌Java代码的混乱方式了,这种方式跟ASP又有什么区别呢?
冷月葬花魂 该用户已被删除
7#
发表于 2015-2-9 22:09:41 | 只看该作者
Java 不同于一般的编译执行计算机语言和解释执行计算机语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码。从而实现了“一次编译、到处执行”的跨平台特性。
山那边是海 该用户已被删除
8#
发表于 2015-3-9 15:23:42 | 只看该作者
自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
灵魂腐蚀 该用户已被删除
9#
发表于 2015-3-10 23:53:28 | 只看该作者
[url]http://www.jdon.com/[/url]去下载,或到同济技术论坛的服务器[url]ftp://nro.shtdu.edu.cn[/url]去下,安装上有什么问题,可以到论坛上去提问。
愤怒的大鸟 该用户已被删除
10#
发表于 2015-3-17 16:10:34 | 只看该作者
关于设计模式的资料,还是向大家推荐banq的网站 [url]http://www.jdon.com/[/url],他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。
11#
发表于 2015-3-24 11:30:48 | 只看该作者
当然你也可以参加一些开源项目,一方面可以提高自己,另一方面也是为中国软件事业做贡献嘛!开发者在互联网上用CVS合作开发,用QQ,MSN,E-mail讨论联系,天南海北的程序员分散在各地却同时开发同一个软件,是不是很有意思呢?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-9-28 19:22

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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