|
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明 进入讨论组讨论。
服务接口
作为一个服务开发人员,你必须告诉人们你的服务可以做什么。或者说,你必须声明你的服务的方法。这包括声明客户端传递给你的方法什么(参数)以及服务返回什么(返回类型)。
上面这个接口是为一个叫Advice的服务。它具有一个方法,getAdvice()。你可以调用这个方法,得到一个字符串,里面包含极好的有用的随机选择的建议。(我们选择不在我们假的小类似于UML的图中显示返回类型。这是非常小的事)。 对于Jini和EJB(Enterise JavaBeans---J2EE的核心和灵魂),接口通常是Remote。一个Remote的接口通常意味着开发者写一个基于java.rmi.Remote的扩展java接口。耶,Remote所有方法(意思是Remote接口中的所有方法)必须声明一个java.rmi.RemoteException的异常。一个强制性的异常(checked exception),告诉客户端:“事情变得很糟糕,小心准备。” ![]() 对于Web Services,接口被定义在一个WSDL中(读作“wizdle”,与“fizdle”押韵)----一种特殊格式的XML文档。所以总括来说,你可以在随意的谈话中说以下这段话: “可以说,在jini和ejb中,你通过java接口暴露你自己,但是在web服务中,你通过xml接口暴露你自己。” (准确地说,如果你是一个java开发者,你通过写一个java接口来创建WSDL,按那个在你的开发工具中神奇的红色按钮,将你的java接口变成XML WSDL。这就够了,像他们说的,这超过了一个鸡尾酒会谈话的范围。) ![]() OK,现在我们有了服务,有了暴露我们服务的接口。现在呢?客户端如何知道这个接口?他们如何真正取得这个接口,他们还需要和我们服务交流些什么呢?这要看服务的类型。这3种类型是不同的。你访问Jini,J2EE和Web服务将有少许不同,文章的其他部分将着重于一些细节和主要不同之处。 首先,让我们从一些Java的Remote Method Invocation(RMI)的背景开始。这是大部分的java分布式技术的主干,Jini和EJB都基于此。事实上,自从所有分布式技术在概念上如RMI的技术上运行时,你在这里了解的东西将帮助你弄清楚整个分布式的世界,Java或者非Java的。 ![]() 通过RMI,你写你的服务并将此变成为Remote对象。让其成为Remote仅是小菜一碟---写分布式接口,创建Remote类来实现它。 进入讨论组讨论。
创建remote接口
1. 扩展 java.rmi.Remote
2. 为每个方法声明java.rmi.RemoteException
1. public interface Advice
2. extends java.rmi.Remote {
3.
4. String getAdvice() throws
5. java.rmi.RemoteException;
6.
7. }
创建remote类
1. 实现你的Remote接口
2. 为接口方法写真正的商业逻辑
1. public class AdviceImplementation implements Advice {
2.
3. public String getAdvice() {
4.
5. // monumentally important
6. business logic here
7.
8. }
9.
10. }
暴露rmi
如果你有个客户端,你想通过远程服务(或者说远程对象)做些东西,你必须有远程服务的接口(在编译时和运行时),而且你必须有stub对象(运行时)。记住,是Stub真正知道如何传递你的方法调用给远程对象(并传递回返回值),所以你可不能没有它。很多时候,你将从服务开发者那得到接口和stub .class文件。 但是有个更酷的方式运行时取得stub类而不需要在运行前取得,那就是通过一个叫动态代码下载(Dynamic code downloading)的进程。这是你在java中可以使用的最强大的东西之一,而且也不难。但是,你也可以以守旧的方式从开发者的Email中取得stub类文件,或者从别人那里下载到你的电脑。 查找服务(例如拥有stub,这样你可以调服务中的商业方法) 在RMI中,你通过RMI登记(附在J2SE中)查找到stub。RMI登记就像一本小的电话簿,你找到名字,然后就得到stub。记得当stub对象过来的时候是串行化的。这意味着在其来到客户端时要使其反串行化。同时为了让其工作,the stub类必须在当前的classpath中或者可以用动态代码下载来找到。这是java基本知识---一个实例不能在没有其类时反串行化。 ![]() 发现查找服务(rmi Registry) 通过RMI,你必须知道the stub在哪里?你必须为RMI Registry知道IP地址和TCP端口号(同时也恰好是远程对象/服务所在的服务器那里)。事实上我们大概并不一定要知道端口号,因为有默认的端口号,但是如果服务部署人员更改了,你则需要知道。客户端只做了简单的单行的查找,利用静态方法(java.rmi.Naming.lookup()),这时奇迹发生了,它有了一个即时的反串行化的stub。对象知道如何打电话回家了。 ![]() 现在我们已经注意RMI,这部分将会更有意义。Jini就像是Extreme RMI。我们这里用Extreme这个词是指其运动含义,而不是XP中的意思。 动态发现:服务和查找服务如何发现对方 这是普通的RMI与Jini差别最多的地方。在RMI中,客户端必须知道很多东西,服务必须通过RMI Registry清楚地登记(用逻辑名称),注册必须在与服务的同个机器中。 但是通过Jini,所有东西仅是在那儿,在某处。没有人知道除了接口外的其他东西。这里有句话关于这个的,我们发现这放在这个对话中的战略时刻相当有意义。 “通过jini,服务通常尝试去发现查找服务,客户端也通常发现查找服务,而查找服务通常在让服务和客户端知道他们(查找服务)就在这。所有都是自动的。” ![]() ![]() ![]() ![]() 虽然在Jini中你也可以将整个服务发送给客户端本身,而不是让服务变成服务器上100%的远程对象,但是基本的Jini结构采用RMI。当客户端要求服务的参考时,将取得远程对象的stub(如果服务被实现为一个远程对象),或者重新得到整个该死的服务,在上面进行简单的旧的本地调用。事实上,通过Jini,客户端甚至可以一个混合体或者“智能代理”(公开说这句话会有特别的声望)。--那样,一个非远程java对象包含一个远程对象的stub(就好像,实例变量)。那样,客户端直接对服务进行本地调用,但是服务本身可能会将其跳转,让远程调用到其他地方。“智能代理”可以通过在客户端做某些工作提高在客户端和服务上的表现。 进入讨论组讨论。
Jini架构
Jini和其他所有分布式技术(普通的RMI,EJB和Web services)有另外一个主要不同点是Jini利用分布式租约帮助建立自愈网络。如果Jini服务是远程的,例如,他给客户端一个租约并说:“这是你的租约。如果你不更新它,我将假设你已经离开,我将停止你在这里代表的任何资源。”最新的网络如何保持依赖于这些租约的时长。例如,一个两小时的租约将意味着客户端可能断开将近两个小时,而你(服务)却不知道。多么浪费!另一方面,一个一秒钟的租约意味着最近的网络,但是所有人花费其所有的周期和带宽去更新租约!所以那是笔交易,这依赖于服务的类型以及其他服务质量问题。 自愈型网络另一个很酷的东西是:既然Jini查找服务是一个Jini服务,查找服务给Jini服务一个租约。所以在这种情况下,Jini服务对于Jini查找服务是个客户。那样,当一个普通客户端(或者说,一个本身不是Jini服务的客户端,而是想用Jini服务的程序)来查找一个服务,比如打印机,如果服务没有通过查找服务更新客户端将不视其为“可用”。此外,租约时间越短,就越是最近的网络的写照,越不可能会令到一个客户选择一个不再可用的服务。 ![]() ![]() Jini暴露 如果你是一个客户端,你想从Jini服务中取得某些东西,你必须有对于这个服务的接口。不想RMI,Jini具有更灵活性,因为你除了接口外不需要知道其他东西。你并不需要知道注册的名字或者Service的位置。只要你知道接口以及你在一个可以发现查找服务的网络,你就可以工作了。 今天,幸运的是开发者给你接口。但是有少量的接口到处漂浮,变成某种标准,包括Bill Venner的名声不好的ServiceUI. 发现服务类 不像RMI,在Jini中你将不可以选择是否使用动态代码下载。你几乎被迫使用它。(你也可以不使用它,但是这违背了Jini的本来目的。)通过Jini,你不需要知道网络中内容的位置,你也不需要知道谁建立这个服务。记着,所有你要的只是接口,而且在很多情况下,你需要担心的你需要去实现服务的接口(也许是个stub,也许是真正的服务,或者集合体…)。 记着,在RMI中,你在客户端中需要的类通常是Stub类,而不是服务本身。在Jini中,如果服务被实现为远程对象,或者是真实的服务,你调用方法的应该在stub中---例如,一个实现了接口并真正工作的类就在客户端本地。 进入讨论组讨论。
查找服务
通过Jini,你使用Jini 查找服务(lookup service),而不是RMI Registry。Jini查找服务更灵活和强大,而且它可以像服务对象那样提供信息给你,哪个,是或者不是远程对象stub,这依赖于服务是否是个服务器上的远程对象或者是转载在客户端上的非远程对象。最好的东西是你不需要知道查找服务在哪!在RMI中,你必须知道远程服务的IP地址和端口号来找到服务stub所在的RMI Registry。而在Jini中,你仅知道大概在某处,在那儿的网络上有不少于一个的查找服务,通过IP广播达到。 这就是Jini。但是Jini是个疯狂的边缘,这里没有人知道任何东西,而你就在你自己的模型上,J2EE正好是相反的东西。
J2EE的主要思想就是服务器(通过容器)给你一堆额外的服务,否则这些服务你也许要自己写,或者将不同的部分拼凑起来,或者从私人厂商那购买。我们现在谈论的是巨型的服务,像事务管理,并行管理,安全,资源/生命周期管理,查找服务,持久化,信息服务等等。 那样,你开始专注于你的自己的商业规则,而不是重新去做那些繁琐的重复的事情。其他应用服务器已经存在了一段时间了---如CICS和TUXEDO都是经典的例子。但是在那种环境下你必须学私有的API,你被厂商锁住了。J2EE是企业级商业中间层的标准,所以你仅仅需要学一个API,无需考虑你要选择的服务器。其中最好的就是你可以部署你的应用到任何符合J2EE标准的服务器,所以你可以对厂商的枷锁说拜拜了。 当然,事实上由于各种原因,将J2EE程序部署在不同的服务器上并不容易。但是你可以。而且如果你有足够的钱换掉你现在的提供商,知道这个不更好?更好的是,让厂商知道你可以这样做。 首先,澄清一下J2EE和EJB的不同:J2EE是一个为可运行EJB的服务器设立的规范。但是J2EE服务器同样要支持servlets和。你可以认为J2EE就像一个整合的服务器—将servlet和支持JSP的Web服务器以及EJB服务器整合在一起的服务器。在J2EE领域,我们叫它子服务容器。所以我们在J2EE服务器中拥有Web容器和EJB容器。因为beans比servlets和JSP更吸引人,我们在这里专注于EJB方面。同时在EJB的世界,服务就是bean。 EJB有样很酷的东西就是基于的开发模型。你建立可重用组件,这些组件是可以在部署时定制而不需要改动java代码。组件比java类更易用,所以他是下一个层次的重用。你利用XML文件来部署你的组件(例如beans),而这些文件说明服务器应该如何处理bean,所以你可以配置安全,事务,资源使用等等,都声明在XML文件中,你只需要在开发工具中按几个按钮即可。(如果你真的想,你当然可以直接编写XML文件。但是现在的工具十分好,而你并不需要去做那些工作。) 进入讨论组讨论。
J2EE架构
J2EE和普通RMI一个很大不同之处就是服务器必须介入客户的调用和服务(例如bean)的被调用中。如果客户端远程调用已开放的bean方法,服务器会介入并让其隐蔽的过多的bean与客户端直接联系。例如,假如客户端扮演特定的顾客调用bean中的getAddress()方法。首先,服务器必须验证客户端是否经授权去调用这个方法,但是假设客户通过了安全检查,现在服务器必须去做其他东西让bean准备好去接受调用。如果bean返回客户的地址,比方bean会重新去记录中取得客户的资料。这需要变成事务的一部分,而其他客户也许准备好使用这个客户,还有…. J2EE的解决方案是让bean成为非远程对象,被远程对象保护。所以即使bean真的是服务(或者说,这里含有客户想调用的商业逻辑服务方法),而bean在RMI方式中并非是远程的。但是客户依然和RMI副本以及远程对象相互作用;就像和EJB相互作用那样,远程对象更像是bean的保镖。远程对象(在J2EE中叫做EJB对象)接受客户端远程调用(例如,客户端在stub上的调用),并同时让服务器加入来决定如何,何时和调用是否到达bean。
J2EE暴露 通过EJB,在RMI规划图(除了服务外)中加入另一层。EJBObject是远程对象,但不像RMI中,EJBObject并不是个服务。所以那样现在这里对于服务有两个帮手,而不像普通的RMI那样子有一个(stub)。你的服务接口依然是远程接口,而不是直接实现java.rmi.Remote,你的服务接口实现EJBObject---一个本身扩展自java.rmi.Remote的接口。尽管bean不含有相同的方法,注意bean如何不扩展服务接口(Advice)。(不要过于拘谨担心,绝大多数注重EJB的开发工具确认bean和服务接口会匹配。) ![]() 找寻服务接口 通过J2EE,你通常与客户端开发者同在一个企业工作,则你可发Email给他接口,或者你可以在内部的知识库中公布。无论如何,重要的是,就像RMI和Jini,客户端必须在编译时有此接口。 同样,对stub类 ,你可以选择提前给客户端或者用动态代码下载。但是这种情况下动态代码下载依赖于你特定的J2EE服务器,也许不可行,所以你也许会被困于自行将stub类传递给客户端的情况。大多数J2EE服务器为你部署bean准备了小而精的客户JAR。 找到服务 警告:我们在这节扩展了鸡尾酒会知识的限制,所以这段人们就会说:”哇噢,在你写到这之前我都跟得上你。。。”这不是我的错,是我们的。所以这里如果你想掠过,你可以直接跳入Web服务,别人也不会知& 进入讨论组讨论。
|
















