您的位置:首页 > 其它

[原创]谈SOA在实际项目中的运用

2007-12-03 15:09 513 查看
大家好,我是bluesky35,现在在IBM ISSC工作,最近做的项目是关于SOA的,号称是上海前几家,呵呵,有了一些心得,想和大家一起交流分享一下.
提到SOA(Service-Oriented Architecture) 面向服务架构,大家恐怕都不陌生, 它是一种架构模型,可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署、组合和使用。SOA中最重要的莫过于服务层,它可以直接被应用调用,从而有效控制系统中与软件代理交互的人为依赖性。
好了,关于SOA的概念网络上有许多,我就不再老生常谈了,接下来还是给大家演示一个SOA的典型用例,我将项目中的一些组件代码抽出,聚合成可使用的sample,简单给大家讲一下.我们要做的是建立一个简单的SOA服务构架,然后从本地访问服务并且从服务中获得基础信息.
基于其中一些朋友可能是初学,所以给大家演示时我尽量做到傻瓜式,即使一点也不懂的朋友也可以跟着例子一步一步走下去,相信这篇文章能给大家带来意外的收获.
首先,我们用java来做这个例子,请大家先在本地安装以下软件:
1. JDK 1.5.0
2. Eclipse 3.2.0

让我们开始吧!
一. 打开eclipse,新建Java Project工程,起名为SOASample,JRE选择1.5,如下图所示:





二. 既然SOA涉及到本地和服务层之间的交互,那一定需要交互的中间介质,毫无疑问是一个保存数据的对象,做欧美项目的朋友叫做BEAN,做对日项目的朋友叫做DTO,我们创建的DTO包含一个属性name_,让我们按下图建立一个DTO.





三. 完善DTO的代码(注意:由于需要在网络中进行传输,所以应该进行序列化,即实现Serializable)

[align=left]import java.io.Serializable;[/align]
[align=left] [/align]
[align=left]publicclass RmiServiceDTO implements Serializable{[/align]
[align=left] [/align]
[align=left] /**[/align]
[align=left] *serialVersionUID[/align]
[align=left] */[/align]
[align=left] privatestaticfinallongserialVersionUID = 1L;[/align]
[align=left] [/align]
[align=left]/**[/align]
[align=left] *serialVersionUID[/align]
[align=left] */[/align]
[align=left] private String _name = null;[/align]
[align=left] [/align]
[align=left] /**[/align]
[align=left] *@return_nameを戻します。[/align]
[align=left] */[/align]
[align=left] public String getName() {[/align]
[align=left] return_name;[/align]
[align=left] }[/align]
[align=left] /**[/align]
[align=left] *@param_name_nameを設定。[/align]
[align=left] */[/align]
[align=left] publicvoid setName(String _name) {[/align]
[align=left] this._name = _name;[/align]
[align=left] }[/align]
[align=left]}[/align]

现在大家的环境应该都与下图一致.



四. 由于SOA需要与服务进行交互,所以我们得建立一个基于RMI的远程接口,与前面建立DTO一样,我们建立名为RMIImpl的接口,代码如下:
[align=left]publicinterface RMIImpl extends java.rmi.Remote{[/align]
[align=left] public RmiServiceDTO execute() throws java.rmi.RemoteException;[/align]
[align=left]}[/align]
[align=left] [/align]



五. 大家都知道,访问服务一般都使用代理模式,即在本地建立代理,然后通过代理访问服务,接收结果.接下来我们建立一个实现以上RMIImpl接口的名为RMIImplProxy的代理,代码如下:
[align=left]import java.rmi.Naming;[/align]
[align=left] [/align]
[align=left]publicclass RMIImplProxy implements RMIImpl{[/align]
[align=left] [/align]
[align=left] public RmiServiceDTO execute() throws java.rmi.RemoteException{[/align]
[align=left] [/align]
[align=left] RmiServiceDTO message = null;[/align]
[align=left] [/align]
[align=left] try{[/align]
[align=left] RMIImpl obj = (RMIImpl)Naming.lookup("/HelloServer");[/align]
[align=left] message = obj.execute();[/align]
[align=left] [/align]
[align=left] }catch(Exception e){[/align]
[align=left] System.out.println(e.toString());[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] // 戻る[/align]
[align=left] return message;[/align]
[align=left] }[/align]
[align=left]}[/align]



在这个代理中,我们通过Naming寻找网络上的名为HelloServer的服务,找到后我们调用该服务的execute方法取得发返回结果.

六. 代理的使用方法有很多种,其中最简单的方式是将它直接实例化使用,为了能在多个代理之间进行统一管理,我们选择工厂方式,接下来我们建立一个工厂,通过调用这个工厂,我们可以获得任何一个代理,代码如下:
[align=left]publicclass ServiceFactory {[/align]
[align=left] [/align]
[align=left] privatestaticfinal ServiceFactory instance = new ServiceFactory();[/align]
[align=left] [/align]
[align=left] private ServiceFactory() {[/align]
[align=left] super();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] /**[/align]
[align=left] *このクラスのインスタンスを取得します.[/align]
[align=left] *@returnこのクラスのインスタンス[/align]
[align=left] */[/align]
[align=left] publicstatic ServiceFactory getInstance() {[/align]
[align=left] returninstance;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] publicRMIImpl getGUSO() {[/align]
[align=left] returnnew RMIImplProxy();[/align]
[align=left] }[/align]
}



七. 接下来我们调用工厂取得代理对象,通过代理对象可以访问远程服务,本地客户端执行代码如下所示:
[align=left]import java.rmi.RemoteException;[/align]
[align=left] [/align]
[align=left]publicclass Client {[/align]
[align=left] [/align]
[align=left] publicstaticvoid main(String[] args) {[/align]
[align=left] [/align]
[align=left] // Serviceを作成[/align]
[align=left] ServiceFactory factory = ServiceFactory.getInstance();[/align]
[align=left] [/align]
[align=left] try {[/align]
[align=left] // Greenサービス実行[/align]
[align=left] RmiServiceDTO rmiServiceDTO = factory.getGUSO().execute();[/align]
[align=left] [/align]
[align=left] System.out.println(rmiServiceDTO.getName());[/align]
[align=left] } catch (RemoteException e) {[/align]
[align=left] e.printStackTrace();[/align]
[align=left] }[/align]
[align=left] }[/align]
}



八. 至今为止,客户端的所有代码都已编写完成,接下来我们模拟一个服务器端服务供客户端调用,代码如下:
[align=left]import java.rmi.*;[/align]
[align=left]import java.rmi.server.*;[/align]
[align=left] [/align]
[align=left]publicclass HelloServer extends UnicastRemoteObject implements RMIImpl{[/align]
[align=left] /**[/align]
[align=left] *[/align]
[align=left] */[/align]
[align=left] privatestaticfinallongserialVersionUID = 1L;[/align]
[align=left] [/align]
[align=left]public HelloServer() throws RemoteException{[/align]
[align=left] super();[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] public RmiServiceDTO execute() throws java.rmi.RemoteException{[/align]
[align=left] [/align]
[align=left] RmiServiceDTO rmiServiceDTO = new RmiServiceDTO();[/align]
[align=left] [/align]
[align=left] rmiServiceDTO.setName("zhaolin");[/align]
[align=left] [/align]
[align=left] return rmiServiceDTO;[/align]
[align=left] }[/align]
}



客户端调用服务,返回一个持有内容为zhaolin的DTO.

九. 由于服务需要启动才能被调用,所以我们再写一个注册程序注册这个服务以便客户端调用,注册程序代码如下:
[align=left]import java.rmi.Naming;[/align]
[align=left] [/align]
[align=left]publicclass RegistIt {[/align]
[align=left] [/align]
[align=left] publicstaticvoid main(String[] args) {[/align]
[align=left] try{[/align]
[align=left] HelloServer obj = new HelloServer();[/align]
[align=left] System.out.println("Object is" + obj);[/align]
[align=left] Naming.rebind("/HelloServer",obj);[/align]
[align=left] System.out.println("Already Start");[/align]
[align=left] }catch(Exception e){[/align]
[align=left] System.out.print(e);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left][/align]



十. 好了,最后要做的就是测试我们之前所写的所有代码,测试这个程序一共有三个步骤.
1. 启动JAVA的服务注册许可
2. 注册并启动服务
3. 调用客户端访问服务取得信息

首先,启动java的服务注册许可,使用命令rmiregistry -J-Djava.security.policy=java.policy启动注册表,如下图所示:



一定要注意:请在所有class的根目录下注册,比如我是将所有代码和class放在E:/SOASample目录下,所以我便在E:/SOASample目录下执行以上注册语句.

然后我们注册并启动服务,在eclipse中执行RegistIt.java,结果如下:



最后我们执行Client.java,通过工厂方式实力化代理对象,通过代理对象访问服务并取得数据,最后的执行结果如下:


整个例子完成了, 有一点需要提一下,在这个例子中,我们是通过模拟的服务返回结果,而在实际应用中,这个服务被单独建立在服务器端,并且服务之间也有通讯,这些服务不一定就是java所写,也可能是使用cobol等语言写的程序,当服务变更,我们只需要调用不同的Proxy即可,而在实际应用中,一个服务就对应一个Proxy,而一个Factory中可以装载所有可供选用的Proxy.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: