|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
有了这样一个呼声:让java代替C语言成为基本语言。这些足以说明java简单易学的这个优点。其次,java的功能强大,前面我也提到了,EJB3.0的推出使java成为了大型项目的首选。当您在使用架构顶用到命令形式(CommandPattern)或服务器端代办署理计划形式(ServerDelegateDesignpattern)时,本章形貌的事件计划形式就对照合适了。在本形式中,服务器端代办署理组件,作为对服务器的远程接进点,具有事件并卖力对事件实行周全的办理。其他任何组件,包含客户端组件、范畴服务组件、或是耐久化组件都不卖力办理事件,它们乃至不会发觉到它们正在利用到了事件。
命令形式是一种十分有效的计划形式,它办理了关于客户端事件办理和EJB中的良多罕见成绩。这类计划形式面前最基础的准绳是,客户端功效被包装在所谓”命令(command)“中,提交给服务器端以便实行。该命令大概包括了一个或多个对范畴服务办法的挪用。但是,这些范畴服务办法的挪用都是经由过程服务器真个被称为“命令完成(CommandImplementation)”的对象往实行的,而不是在客户端实行。利用命令形式,使得用户能够从客户端对范畴服务组件倡议单一哀求,并同时同意服务器端而不是客户端来办理事件处置历程。
服务器端代办署理形式的机制相似,独一分歧的是,它没有利用相似于命令形式的框架,而是复杂地将客户侧的营业代办署理逻辑安排在服务器真个代办署理对象中往了。终极了局是一样的,事件处置历程被移到了服务器端,而且客户端对服务器的哀求从多个削减到一个。
“服务器端代办署理具有事件的计划形式”是“范畴服务具有事件形式”的惯例。二者的次要区分在于,假如利用命令形式,会有“一个自力的对象”具有事件,而不是由“一类组件”具有事件。比方,假如您的使用包括40个分歧的范畴服务,在“范畴服务具有事件形式”下,大概由40个bean往办理事件。但是,在“服务器端代办署理具有事件的计划形式”下,您只必要一个bean(命令实行者,CommandProcessor)往办理事件。
背景(Context)
上面的代码示例展现了在EJB情况下,为了完成一个营业哀求,客户端对象必需构成屡次对服务器挪用的场景。- publicclassClientModel{publicvoidplaceFixedIncomeTrade(TradeDatatrade)throwsException{InitialContextctx=newInitialContext();UserTransactiontxn=(UserTransaction)ctx.lookup("java:comp/UserTransaction");try{txn.begin();...Placementplacement=placementService.placeTrade(trade);executionService.executeTrade(placement);txn.commit();}catch(TradeUpdateExceptione){txn.rollback();log.fatal(e);throwe;}}}
复制代码 在这个实例中,客户端必需利用编程式事件来确保一个自力的事件性事情单位中满意ACID特征。在此情况下,不单单是客户端要卖力事件办理,并且由于屡次对(远端)范畴服务的挪用,功能也遭到影响。另有,在这个例子中,范畴服务由无形态会话Bean的EJB完成,更年夜水平上使得架构庞大化。- [/code]为了简化此类情形,我们必要将无形态会话Bean完成的范畴服务重构为POJO,从客户端移除事件逻辑,尔后为所触及的一切客户端哀求机关一个单一的对服务器真个挪用。我们可使用命令形式或是服务器端代办署理计划形式往到达部分或全体的方针。当使用这两个形式中任何一个时,原本位于客户层的事件处置将被搬移到服务器层了。上面的代码示例展现了使用命令形式后,修改过的客户端代码:
- [code]publicclassClientModel{publicvoidplaceFixedIncomeTrade(TradeDatatrade)throwsException{PlaceFITradeCommandcommand=newPlaceFITradeCommand();command.setTrade(trade);CommandHandler.execute(command);}}
复制代码 能够看出,这是对之前代码做了十分年夜简化的版本。但是,有一个成绩留上去了,“事件处置的逻辑在那里呢”?在这个场景中,可使用“服务器端代办署理者具有事件”计划形式,鉴别由哪一个组件卖力事件办理,和对这些组件声明式事件该怎样设定。
制约前提(Forces)
- 利用命令形式和服务器端代办署理计划形式计划使用架构和客户端与服务器的通讯。
- 客户端老是与服务器端代办署理举行单一交互以完成营业哀求。
- 必需包管ACID特征,意味着必要举行事件处置以保护数据完全性。
- 范畴服务对象利用POJO完成,能够位于远程或当地。
- 命令处置器或服务器端代办署理是从客户端到范畴服务的单一会见点。
办理计划(Solution)
当利用命令形式或服务器端代办署理计划形式时,服务器端代办署理者具有事件计划形式可以作为此类使用架构的全体事件计划战略。该形式利用将全部事件办理的义务放在服务器端代办署理组件上的义务模子。当利用命令形式时,服务器端代办署理组件完成为单一的命令处置器(CommandProcessor)组件,该组件定位有关的命令完成对象并实行命令。在EJB中,该组件一般被完成为无形态会话Bean。在Spring中,它能够被完成为Spring办理的bean(POJO)。当利用服务器端代办署理计划形式时,每一个客户端哀求的功效汇合能够完成为相互自力的服务器端代办署理(Spring中的POJO或是EJB中的SLSB)。
下图申明了在EJB和Spring框架两种情形下本形式的完成细节:
<br>
服务器端代办署理组件利用声明式事件,有关的更新办法被付与Required的事件属性,而一切的读取办法被付与Supports属性。服务器端代办署理组件在处置使用非常时,也会卖力挪用setRollbackOnly()办法。
这类形式合用的使用架构十分单一。在命令形式的用例下,服务器端代办署理被完成为命令处置器,复杂地吸收客户端发送来的命令对象,实行这些命令。在命令形式框架下自始至终利用接口(interface)的编程作风则包管了命令吸收(CommandHandler)组件、命令处置(CommandProcessor)组件、命令完成接口(CommandImplementationInterface)、和命令接口(CommandInterface)自己都坚持通用和使用有关性。服务器端代办署理创建的事件高低文被传布到它挪用到的一切对象。
在服务器端代办署理计划形式中,服务器端代办署理组件是作为对使用架构中范畴服务组件的客户端门面存在的。在这类计划形式中,客户真个逻辑实践上被搬到了服务器,并放在客户端代办署理组件中。
这些计划形式的次要弱点是,服务器端代办署理组件包括了客户真个逻辑,而不是纯的服务器逻辑。而且,本形式在良多情形下对照难于完成,由于客户端营业代办署理经常是与利用的web框架严密绑定的。这类情形间接的例子是struts,在struts框架中Action类具有饰演客户端营业代办署理脚色的才能(现实上良多时分它也是这么用的)。别的,大概将客户端逻辑搬走很难,由于其代码包括了对完整基于客户真个对象,比方HTTPSesssion、HTTPRequest,和HTTPResponse的援用,这些对象要搬到服务器侧往是对照坚苦的。
但是,这两种计划形式最为分明的一个上风在于,包括处置哀求营业逻辑主体的范畴服务组件完成为POJO(复杂Java对象),而不是EJB。因而范畴服务组件从EJB框架中解耦合,使得它们易于测试。服务器端代办署理具有事件的计划形式另外一个共同的地方在于,因为服务器端代办署理经常完成为一个无形态会话Bean的单例(singleton)组件,全部使用的事件逻辑位于单一的对象内。因而,从完成和保护的概念讲,它是最复杂的事件计划形式。而且,该事件计划形式将事件办理的义务重任放在了范畴服务组件的下面一层,将使用中服务器真个中心功效处置务办理之类的基本架构方面中束缚了。经由过程利用本形式,范畴服务组件可用POJO编写,因为它们不包括事件逻辑,在容器外的情况中测试就非常便利。
成果(Consequences)
- 客户端(不管哪一种范例)不包括任何事件逻辑,不论理事件处置的各个方面。
- 因为服务器端代办署理组件开启和办理事件,更新办法在碰着使用非常时必需挪用setRollbackOnly()办法。
- 服务器端代办署理创建的事件被传布到基于POJO的范畴服务对象,同时也传布到范畴服务用到的耐久化对象(不管利用哪种耐久化框架)。并且,这些组件不包括任何事件或回滚的逻辑。
- 服务器代办署理对象利用声明式事件,对更新相干的办法使用Required的事件属性,对读取操纵使用Supports属性。
- 为了保护ACID特征,客户端对象毫不开启事件、提交事件,或将事件标志为回滚。
- 耐久化对象和范畴服务不包括任何事件或回滚逻辑。
- 假如利用EJB2.1的实体Bean,更新操纵的事件属性必需设置为Mandatory,其实不要利用任何回滚逻辑。对读取操纵而言,假如利用容器办理耐久化(Container-managedPersistence,CMP),必要为实体Bean设置Required的事件属性;假如利用Bean办理的耐久化(Bean-managedPersistence,BMP),则必要设置事件属性为Supports。
完成(Implementation)
上面的代码分离展现了EJB和Spring下这类形式的完成。为举例便利的必要,我们假定利用命令形式。对EJB,我假定命令处置器用无形态会话Bean完成;对Spring,我假定命令处置器为Spring框架所办理。
EJB
在命令形式下,该事件计划形式只要一个组件包括事件代码(即事件处置器组件)。因而,因为客户端不包括事件代码,我们仅唯一需要展现服务器端代办署理(事件处置器)关于这个形式的代码完成。EJB中的范畴服务组件,针对更新和读取操纵的代码以下所示(事件逻辑用粗体暗示):- @StatelesspublicclassCommandProcessorImplimplementsCommandProcessor{@TransactionAttribute(TransactionAttributeType.SUPPORTS)publicBaseCommandexecuteRead(BaseCommandcommand)throwsException{CommandImplimplementationClass=getCommandImpl(command);returnimplementationClass.execute(command);}@TransactionAttribute(TransactionAttributeType.REQUIRED)publicBaseCommandexecuteUpdate(BaseCommandcommand)throwsException{try{CommandImplimplementationClass=getCommandImpl(command);returnimplementationClass.execute(command);}catch(Exceptione){sessionCtx.setRollbackOnly();throwe;}}}
复制代码 下面例子中的getCommandImpl()办法利用反射(reflection)来装载和实例化命令完成对象。尔后它被实行,然后经由过程命令对象向客户端前往了局。注重,该完成与“范畴服务具有事件的计划形式”十分类似,由于我们对读取操纵附加了Supports的事件属性,而且对更新相干操纵附加了Required的事件属性,并辅以setRollbackOnly()办法。- [/code][b]Spring框架[/b]
- 在Spring框架下,这个形式完整经由过程Spring的XML设置文件完成。在EJB完成中必要挪用setRollbackOnly()办法,而在Spring中,经由过程设置文件中的回滚划定规矩指令就能够处置了。以下的设置代码展现了本形式怎样设置服务器端代办署理组件(命令处置器)去向理更新和读取操纵(事件逻辑加用粗体):
- [code]<!--界说服务器端代办署理命令处置器--><beanid="commandProcessorTarget"class="com.commandframework.server.commandProcessorImpl"></bean><beanid="commandProcessor"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><propertyname="transactionManager"ref="txnMgr"/><propertyname="target"ref="tradingServiceTarget"/><propertyname="transactionAttributes"><props><propkey="executeUpdate">PROPAGATION_REQUIRED,-Exception</prop><propkey="executeRead">PROPAGATION_SUPPORTS</prop></props></property></bean>
复制代码 由于这个形式针对服务器端代办署理组件断定了声明式事件的利用,在范畴服务组件中不管是更新仍是读取的代码都不包括任何事件逻辑。如之前讲到的,setRollbackOnly()的逻辑被Spring主动处置了,我们能够从下面XML代码中-Exception那一段看出眉目。上面则演示了在Spring中完成该形式不必要任何事件逻辑的Java代码:- publicclassCommandProcessorImplimplementsCommandProcessor{publicBaseCommandexecuteRead(BaseCommandcommand)throwsException{CommandImplimplementationClass=getCommandImpl(command);returnimplementationClass.execute(command);}publicBaseCommandexecuteUpdate(BaseCommandcommand)throwsException{CommandImplimplementationClass=getCommandImpl(command);returnimplementationClass.execute(command);}}
复制代码 注重,在本例中,Spring在两个办法中的完成本色上做了一样的事变。不像EJB完成,非常处置其实不需要,由于setRollbackOnly逻辑已包括在XML的回滚战略设置中了。
关于作者
MarkRichards是IBM认证的初级IT架构师,他在IBM公司处置年夜型体系面向服务架构的计划和架构事情,利用J2EE与其他手艺,次要为金融行业服务。作者早在1984年起就到场软件行业,从开辟职员做起,直至计划师、架构师。他常常在出名论坛“NoFluffJustStuff”演讲,他从波士顿年夜学猎取了盘算机迷信硕士学位,持有SUN、IBM、BEA的多个Java与架构师认证。若有关于本书的批评或疑问,尽请接洽Mark。
本文选自迷你书《Java事件计划战略》的第九章,译者翟静。
进而能拉拢大多数程序员用windows产品。并且从net网页编程网页编程AJAX可以跨平台这一点上,间接证明了我们的推断,至少证明了微软做过这方面的研究。所以如果哪一天突然听说了.net网页编程可以跨平台了,那么请不要吃惊,如果这一天真的到来,java就到了真正和.net网页编程决战的时刻。因为不到万不得以的时候微软是不会推出跨平台的.net网页编程的,如果跨平台的.net网页编程还不足以对抗java的话,那么微软还剩的手段就是开源了,呵呵。 |
|