大家好
,
我是
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)
import
java.io.Serializable;
public
class
RmiServiceDTO
implements
Serializable{
/**
*
serialVersionUID
*/
private
static
final
long
serialVersionUID
= 1L;
/**
*
serialVersionUID
*/
private
String
_name
=
null
;
/**
*
@return
_name
を戻します。
*/
public
String getName() {
return
_name
;
}
/**
*
@param
_name
_name
を設定。
*/
public
void
setName(String _name) {
this
.
_name
= _name;
}
}
现在大家的环境应该都与下图一致.
四. 由于SOA需要与服务进行交互,所以我们得建立一个基于RMI的远程接口,与前面建立DTO一样,我们建立名为RMIImpl的接口,代码如下:
public
interface
RMIImpl
extends
java.rmi.Remote{
public
RmiServiceDTO execute()
throws
java.rmi.RemoteException;
}
五. 大家都知道,访问服务一般都使用代理模式,即在本地建立代理,然后通过代理访问服务,接收结果.接下来我们建立一个实现以上RMIImpl接口的名为RMIImplProxy的代理,代码如下:
import
java.rmi.Naming;
public
class
RMIImplProxy
implements
RMIImpl{
public
RmiServiceDTO execute()
throws
java.rmi.RemoteException{
RmiServiceDTO message =
null
;
try
{
RMIImpl obj = (RMIImpl)Naming.lookup(
"/HelloServer"
);
message = obj.execute();
}
catch
(Exception e){
System.
out
.println(e.toString());
}
//
戻る
return
message;
}
}
在这个代理中,我们通过Naming寻找网络上的名为HelloServer的服务,找到后我们调用该服务的execute方法取得发返回结果.
六. 代理的使用方法有很多种,其中最简单的方式是将它直接实例化使用,为了能在多个代理之间进行统一管理,我们选择工厂方式,接下来我们建立一个工厂,通过调用这个工厂,我们可以获得任何一个代理,代码如下:
public
class
ServiceFactory {
private
static
final
ServiceFactory
instance
=
new
ServiceFactory();
private
ServiceFactory() {
super
();
}
/**
*
このクラスのインスタンスを取得します
.
*
@return
このクラスのインスタンス
*/
public
static
ServiceFactory getInstance() {
return
instance
;
}
public
RMIImpl
getGUSO() {
return
new
RMIImplProxy();
}
}
七. 接下来我们调用工厂取得代理对象,通过代理对象可以访问远程服务,本地客户端执行代码如下所示:
import
java.rmi.RemoteException;
public
class
Client {
public
static
void
main(String[] args) {
// Service
を作成
ServiceFactory factory = ServiceFactory.getInstance();
try
{
// Green
サービス実行
RmiServiceDTO rmiServiceDTO = factory.getGUSO().execute();
System.
out
.println(rmiServiceDTO.getName());
}
catch
(RemoteException e) {
e.printStackTrace();
}
}
}
八. 至今为止,客户端的所有代码都已编写完成,接下来我们模拟一个服务器端服务供客户端调用,代码如下:
import
java.rmi.*;
import
java.rmi.server.*;
public
class
HelloServer
extends
UnicastRemoteObject
implements
RMIImpl{
/**
*
*/
private
static
final
long
serialVersionUID
= 1L;
public
HelloServer()
throws
RemoteException{
super
();
}
public
RmiServiceDTO execute()
throws
java.rmi.RemoteException{
RmiServiceDTO rmiServiceDTO =
new
RmiServiceDTO();
rmiServiceDTO.setName(
"zhaolin"
);
return
rmiServiceDTO;
}
}
客户端调用服务
,
返回一个持有内容为
zhaolin
的
DTO.
九. 由于服务需要启动才能被调用,所以我们再写一个注册程序注册这个服务以便客户端调用,注册程序代码如下:
import
java.rmi.Naming;
public
class
RegistIt {
public
static
void
main(String[] args) {
try
{
HelloServer obj =
new
HelloServer();
System.
out
.println(
"Object is"
+ obj);
Naming.rebind(
"/HelloServer"
,obj);
System.
out
.println(
"Already Start"
);
}
catch
(Exception e){
System.
out
.print(e);
}
}
十. 好了,最后要做的就是测试我们之前所写的所有代码,测试这个程序一共有三个步骤.
1. 启动JAVA的服务注册许可
2. 注册并启动服务
3. 调用客户端访问服务取得信息
首先,启动java的服务注册许可,使用命令rmiregistry -J-Djava.security.policy=java.policy启动注册表,如下图所示:
一定要注意:请在所有class的根目录下注册,比如我是将所有代码和class放在E:/SOASample目录下,所以我便在E:/SOASample目录下执行以上注册语句.
然后我们注册并启动服务,在eclipse中执行RegistIt.java,结果如下:
最后我们执行Client.java,通过工厂方式实力化代理对象,通过代理对象访问服务并取得数据,最后的执行结果如下: