1.  
												
										
								
								
										
												概述
										
										
								
						
				
		
		
				
						
								
										
在前面我已经讲了一些关于SCA的基础知识,使用了本人实现的一个SCA容器做为讲解示例,9月中旬我把这个SCA容器做为开源项目在Sourceforge.net上立项了,并且正式给这个SCA容器取名为Balto。
这一次我将继续使用Balto作为示例SCA容器,并讲一下SCA程序设计中的外部服务(ExternalService)
ExternalService
								在
								SCA
								中可以被看作是一个
								Module
								的应用出口,它定义了
								Module
								所要调用的非
								module
								内部服务的外部服务信息,在SCA程序设计中的地位举足轻重。关于ExternalService的一些基本信息介绍,大家可以看一下我的另一篇文章.
						
				
		
		
				
						
								
										
ExternalService
								虽然描述了外部服务的信息,但是它需要通过
								Binding
								来对该外部服务的访问细节进行描述。关于
								Binding
								的更多信息,也可以查看上面所说的那篇文章。
				
		
		
				
						
								
										
我们接下来将要讲的
								ExternalService
								都是基于
								WebService Binding
								的外部服务。
						
				
		
		
				
						
								
										
										
												2
										
								
								
										
												.ExternalService的
												XML
										
										
												格式
												
										
								
						
				
		
		
				
						
								
										
ExternalService
								的定义需要写在
								sca.module
								文件中,具体格式如下:
						
				
		
		
		
		
				
						
								
								
								
										
										
										
								
						
				
		
		
				
						
						
						
						
								
										
												<
												externalService 
												name
												="xs:NCName"
												 override
												="sca:OverrideOptions"
												?
												>
										
								
								
										
												*
												        <in
												terface
												.interface-type
												/>
										
								
								
										
										
								
								
										
												        <
												binding
												.binding-type uri
												="xs:anyURI"
												/>
										
								
								
										
												*
												</
												externalService
												>
										
								
								
										
								
						
						
								
								
										
												
												
   1)    
								
						
				
		
		
				
						先看
						externalService
						元素,该元素具有两个属性,一个是
						name,
						一个是
						override
						,
						name
						是标识
						externalService
						的名称的,在
						ModuleContext
						中通过
						localService
						定位服务的时候,是通过
						name
						属性所写的名称进行查询外部服务的。
				
		
		
				
						
								
										
												
2)      
								
								Interface
								元素在之前的《本地服务》一文中有介绍,主要是指明该外部服务所对应的接口类型以及位置。一般情况下都使用
								java
								类型的接口:
						
				
		
		
				
						<interface.java interface = “InterfaceClassName”>
				
		
		
				
						
								
										
												
3)      
								
								Binding 在下面会有讲解
				
		
		
				
						
								
										
										
												3.
										
								
								
										
												如何去构建一个可用的外部服务
										
								
						
				
		
		
				
						
								
										
既然是外部服务,有很大程度上都是属于异地节点上的服务,所以很多情况下我们使用外部服务都需要一些远程调用的手段对其进行调用,所以
								ExternalService
								也可以直接看作是一个
								Remote Service
								。
						
				
		
		
				
						
								
										
我们最常见的远程调用方式有以下几种:
								RMI
								、
								EJB
								、
								Web Service
						
				
		
		
				
						
								
										
外部服务远程调用的绑定协议是由
								Binding
								元素给出的,目前
								SCA
								规范中给除了两种
								Binding
								,一种是
								SCABinding
								,这种
								Binding
								方式没有确切的说明;还有一种就是
								WebService Binding
								,顾名思义,这种
								Binding
								是基于
								WebService
								的一种远程调用
								Binding
								。
						
				
		
		
				
						
								
										
一旦
								ExternalService
								指定了明确的
								Binding
								方式后,在调该
								ExternalService
								指定的接口的方法的时候,
								Balto SCA
								容器就会通过
								Java
								的动态接口代理技术,生成一个动态的接口代理,然后通过
								Binding
								的类型以及
								ExternalService
								的一些信息细节,在动态接口代理方法中通过
								Binding
								对应的远程调用协议(比如
								Web Service
								)进行对应的调用,如图所示:
								
								
						
				
		
		
				
						
						
								
								
								
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
								
								
								
								
								
						
				
		
		
				
						
								
										
								
								
										 
								
								
										
										                                             图 1
										
										
										
生成的不同的
						
						InvokeHandler
						会根据协议需要,解析出
						Binding
						类型中的信息细节,然后通过一些远程调用手段去调用该外部服务所在位置的服务实体。
				
		
		
				
						
								
										
										
说得不明不白的,举个
						
						WebService Binding
						的例子会清楚一些:
				
		
		
				
						
								
										
首先我们在
								sca.module
								文件中写入:
						
				
		
		
		
		
				
						
								
								
								
										
										
								
						
				
		
		
				
				
				
				
						
								
										<
										externalService 
										name
										="WeatherProvider"
										>
								
						
						
								
								
								  
						
						
								
										<
										interface
										.java interface
										="net.x.webservice.client.WeatherProvider"
										/>
								
						
						
								
								
								  
						
						
								
										<
										binding
										.ws port
								
						
						
								
										="http://www.webservicex.net/globalweather.asmx?WSDL
                                   #wsdl.endpoint(GlobalWeather/GlobalWeatherSoap)"
										/>
								
						
						
								
						
						
								
										</
										externalService
										>
								
						
						
								
						
				
				
						
						
						
								
这个
				
		
		
				
						externalService
						的含义是,我们讲通过一个
						net.x.webservice.clinet.WeatherProvider
						的接口类
						,去调用一个
						web servicec
						,而这个
						web service
						是通过
						binding.ws
						来描述的,这个
						web service
						的
						wsdl
						的地址是
						
								http://www.webservicex.net/globalweather.asmx?WSDL
						
						,而且该外部服务调用的是这个
						wsdl
						中描述的
						GlobalWeather
						服务,并且这个服务在
						wsdl
						中的
						binding
						名是
						GlobalWeatherSoap
						。
						
						
								
								
						
				
		
		
				
						
								
也就是说,Web Service binding的port属性所需值的格式规范是这样的:
WSDL 1.1 : <WSDL-namespace-URI>#wsdl.endpoint(<service-name>/<port-name>)
WSDL 2.0 : <WSDL-namespace-URI>#wsdl.endpoint(<service-name>/<endpoint-name>)
我们可以利用API通过
						SCA
						的
						ModuleContext
						来定位这个外部服务:
				
				ModuleContext.localService(“WeatherProvider”);
				这段代码将
				
						返回
						
								net.x.webservice.clinet.WeatherProvider
								接口。
						
				
		
		
				
						
								
										
不过这个接口是没有实现的,因为我们不可能在本地去实现这个接口类——我们根本就不知道这个服务的具体业务逻辑。我们只是通过这个接口类的方法调用,来确定所需要调用这个
								Web Service
								所要做的工作。
						
				
		
		
				
						
								
										
根据上面的图
								1 可以清楚的知道,Balto SCA容器去定位一个外部服务的时候,当得到了该远程服务对应的Java接口后,会生成一个接口的动态代理,并且,通过这个远程服务的Binding信息以及一些调用方法信息(参数值,方法名),确定如何利用Axis2 Client去调用远程服务Binding到的那个Web Service。下面是动态代理处理用户调用方法的简要代码介绍:
				
		
		
				
				
				
						
								
						
				
		
		
				
						public
				
				
						
								 Object excute(ExternalService externalService, Binding binding,
                     Object proxy, Method method, Object[] parameters) 
								                                                       throws
						
				
				
						
								 Throwable {
              
								try
						
				
				
						
								 {
                     
								if
								 (binding 
								instanceof
						
				
				
						
								 WebServiceBinding) {
                            WebServiceBinding wsBinding 
								=
						
				
				
						
								 (WebServiceBinding) binding;
 
                            String wsdlURI 
								=
						
				
				
						
								 wsBinding.getWSDLNameSpaceURI();
 
                            WSDLFactory wsdlFactory 
								=
						
				
				
						
								 WSDLFactoryImpl.newInstance();
                            WSDLReader wsdlReader 
								=
						
				
				
						
								 wsdlFactory.newWSDLReader();
                            wsdlReader.setFeature(
								"
								javax.wsdl.verbose
								"
								, 
								true
						
				
				
						
								);
                            Definition definition 
								=
								 wsdlReader.readWSDL(
								null
						
				
				
						
								,
                                                                              wsdlURI);
                            String webServiceName 
								=
						
				
				
						
								 wsBinding.getServiceName();
                            String portName 
								=
						
				
				
						
								 wsBinding.getPortName();
 
                            ……….
                            
								//
								 这是Axis2 Client的调用代码
						
				
				
						
				
				
						
						                            ServiceClient service 
				
				
						
								=
								 
								new
						
				
				
						
								 ServiceClient();
                            Options options 
								=
								 
								new
						
				
				
						
								 Options();
 
                            service.setOptions(options);
                            EndpointReference targetEPR 
								=
								 
								new
						
				
				
						
								 
                                                  EndpointReference(serviceURI);
                            options.setTo(targetEPR);
                            targetEPR.setAddress(serviceURI);
                            service.setTargetEPR(targetEPR);
                            …….
								                            //
								 根据返回值类型来确定调用方式
						
				
				
						
				
				
						
				
				
						
								                            if
								 (returnType 
								==
								 Void.
								class
						
				
				
						
								) {
                                   service.sendRobust(omElement);
                                   
								return
								 
								null
						
				
				
						
								;
                            } 
								else
						
				
				
						
								 {
                                   resultElement 
								=
						
				
				
						
								 service.sendReceive(omElement);
                            }
								                           //
								  处理返回的SOAP体
						
				
				
						
				
				
						
						                            ………
       }
				
		
		
				
				 
		
		
				
						
								这样做的目的是为了屏蔽掉开发人员在调用时候的一些细节处理,开发人员不关心整个
								Web Service
								的调用过程,只需要像调用简单
								java
								类一样调用即可。
						
				
		
		
				
						
								
										
										
												4
										
								
								
										
												.实战——天气预报
										
								
						
				
		
		
				
						
								
										
我们通过一个简单的例子来看看如何使用
								Balto SCA
								来进行做
								ExternalService
								。
								
										示例工程下载
								
						
				
		
		
				
						
								
先考虑这么一个需求:
				
		
		
				
						
								
我们在登录一些网页的时候,网页上会显示出我们所在地当前的天气情况,这种比较个性化的功能常常能吸引不少网民的眼球。
				
		
		
				
						
								
问题是如何去实现呢?
				
		
		
				
						
								
										
首先,我们登录到某个网页上的时候,网站后台会得到我们的访问
								IP
								地址,通过这个地址是可以确定我们现在所在位置的。
						
				
		
		
				
						
								然后,根据我们
								IP
								解析出来的物理位置,查询该地址最近的天气信息。
						
				
		
		
				
						
								
大概是这样去做。
				
		
		
				
						
								
										
但是我们怎么去解析
								IP
								地址获得物理位置呢?这种工作一般需要有一个存储了大量的
								IP
								地址到物理地址映射的数据库,一般情况下我们不可能拥有这样一个数据库。更何况,即使得到了物理地址,我们也不可能通过计算机去计算出当前的天气情况吧??
								
						
				
		
		
				
						
								
										
虽然我们不能做这些工作,但是在网络上存在这大量类似功能的
								Web Service
								。我们可以通过这些免费的
								Web Service
								来定制这么一个功能。
						
				
		
		
				
						
								
										
准备工作:安装
								
										
												Eclipse WTP 1.0
										
								
								,下载
								
										Balto_tomcat_0_0_2
								:
				
				
						
								
										
												
										
										
我在网上找到了两个
								Web Service:
						
				
		
		
				
						
								
										
												
1.       
								
								获得
								IP
								地址和物理地址映射的
								WebService:
						
				
		
		
				   http://ws.fraudlabs.com/ip2locationwebservice.asmx?wsdl
		
		
				
						
								
										
												
2.       
								
								获得天气情况的
								Web Service
						
				
		
		
				   http://www.webservicex.net/globalweather.asmx?WSDL 
				
				
		
		
				
						
								
										
现在需要通过
								Balto SCA
								将这两个
								Web Service
								做成
								ExternalService
								:
						
				
		
		
				
						
								
										
首先将
								Balto_tomcat_test_0_9
								添加到应用服务器中。这里需要说明一下,
								Balto_tomcat_test_0_9
								是整合在
								tomcat
								中的,就是说Balto = Tomcat,Balto替换了tomcat的启动Host入口类,所以在
								tomcat
								启动的时候
								Balto 就会去解析部署的web application,当发现该web应用是一个SCA模块的话,就会对这个web application进行解析,并注册解析出的相关SCA模块信息。当然,这些细节开发人员是不用关心的。
				
		
		
				
				
		
		
				
						
								
										
										 
										
										
										
然后新建一个
								Dynamic Web project
								,对应的
								Target Runtime
								选择刚设定好的
								Tomcat
								服务器。
						
				
		
		
				
						
								
										
接下来我们要将
								Web Service
								的
								WSDL
								中描述的复杂类型数据结构生成
								Java
								静态代码,并且必须是
								SDO
								类型的。这些复杂类型是提供给
								ExternalService
								指定的
								Java
								接口所需的调用参数以及返回结果使用的,因为大家都知道,
								Web Service
								在用
								SOAP
								传送过程中,
								SOAP
								的
								Body信息体
								内是采用的
								XML
								结构文档,并且在操作执行完毕后,
								Web Service
								的返回
								SOAP
								中,也是利用
								XML
								对结果进行描述的,所以
								Balto
								采用
								SDO
								作为复杂类型数据结构,不仅仅是因为
								SCA
								规范中的要求,更多的是为了更好地序列化、反序列化我们的复杂类型
								(Java2X
								ML,XML2Java)
								。
						
				
		
		
				
						
								
										
先将上面提到的两个
								WSDL
								文件下载到本地,然后我们通过这两个
								WSDL
								生成一个
								EMF Model
								:
						
				
		
		
				
						
								
										
								
								
										 
								
								 
						
				
		
		
				
				
		
		
				
				
		
		
				
						
								
								
						
				
		
		
				
						
								
										
								
								
										 
								
								
										
										
完成操作后会生成一个新的 
						
						EMF Model
						文件,打开这个文件的编辑器,选中根节点,在弹出菜单中选择
						Set SDO Defaults
						:
				
		
		
				
				
		
		
				
						
								
										
								
								
										 
								
								
										
 
						
				
		
		
				
						
								完成上述操作后,再在弹出菜单中选择
								Generate Model Code
								,
								Eclipse
								就会自动生成一套
								SDO
								的模型代码,我们还要修改生成的SDO代码中的XXXPackageImpl的createExtendedMetaDataAnnotations方法,将代码中描述Element的name不正确的地方修改过来,并把创建EClass的地方所给出的ImplementClass的地方,将接口类替换成接口的实现类。上述步骤可以看一下《SCA程序设计——远程服务,以及实现远程服务的问题和想法》,其中有具体说明。
						
				
		
		
				
						
								
										
								
						
				
		
		
				
						温馨小贴士:
						Eclipse EMF生成的SDO代码中,用于描述XML的Element名以及对应Java类的XXXPackageImpl类,其中含有一个createExtendedMetaDataAnnotations方法,这个方法中描述了对应Java类以及Java类具有的属性所对应的XML中的Element以及Attribute的名称。但是一般利用XSD或者WSDL直接生成的SDO代码中,EMF会默认给出一个DocumentRoot的类,也就是说这个类才是EMF真正序列化java对象的根节点,如果不利用DocumentRoot包装我们的创建的SDO Java对象,序列化出来的XML就会出现XML名“不正确”的情况,而这种所谓“不正确”情况下Java对象对应的XML名,是在ExtendedMetaDataAnnotations中给出的。当然,上述情况只限于EMF生成的SDO.
				
		
		
				
 
		
				
				
		
		
				
						
								
										 
 
						
				
		
		 
		
				
						
								将
								SDO
								代码生成好后,接下来就需要创建一个接口类。创建的这个接口类就是
								ExternalService
								所要指定的接口类。
						
				
		
		
				
						
								
										
这个接口类需要和ExternalService在Binding中给出的
								WSDL
								的
								PortType
								具有
								相同的操作。使用过
								Axis
								或者
								Axis2
								的读者一定会联想到
								Axis
								以及
								Axis2
								提供给开发人员的
								WSDL2Java
								的工具,这个工具就是将
								WSDL
								生成一套
								Axis
								的客户端,包括复杂类型以及所要调用的
								Web Service
								对应的客户端
								Stub
								。
								Balto
								目前没有提供一个类似的工具(还在开发当中),所以这些工作还需要开发人员自己完成。
						
				
		
		
				
						
								
										
我们现在来为上面提到的查询
								IP
								对应物理位置的
								ip2locationwebservice WSDL
								创建一个
								Interface
								接口类:
						
				
		
		
				
						
								
										
我们给这个接口类取名为
								IP2LocationWebService
								,然后我们查看一个
								ip2locationwebservice
								的
								WSDL
								文件,
						
				
		
		
				
						
								
大家会发现这个
						WSDL
						文件中指定了
						3
						种
						Binding
						方式:
						POST,GET
						和
						SOAP
						,
						Balto
						目前只支持
						SOAP
						,所以我们只关心和
						SOAP Binding
						关联的
						Port Type
						:
						Ip2LocationWebServiceSoap
						。这个
						Port Type
						具有一个
						Operation
						(操作)
						:IP2Location
						,该操作的输入指向是的名为
						IP2LocationSoapIn
						的
						Message
						,而这个
						Message
						的
						Element Type
						是在
						XSD Type
						中定义的
						IP2Location
						类型。看看
						WSDL
						的就会很清楚了:
						
								
								
						
				
		
		
				
				
		
		
				
						
								
										
								
								
										 
								
								
										
 
						
				
		
		
				
						
								所以我们需要给
								IP2LocationWebService
								定义一个方法,方法名需要和
								WSDL
								的
								Operation
								名同名:
								
										
												IP2Location
										
								
								,而这个方法的输入参数应该是刚才所生成的
								SDO
								中的
								IP2LocationTypeImpl
								(注意:
								Eclipse
								通过
								XSD
								生成的
								SDO
								命名规则是一定的,
								SDO
								模型接口命名规则是属性名
								+Type
								;
								SDO
								模型接口实现命名规则是:属性名
								+TypeImpl
								),并且这个操作的返回值类型是一个
								IP2LocationResponseTypeImpl
								,代码如下:
						
				
		
		
				
						
								
						
				
		
		 
		
				
						
								public
								 
								interface
						
				
				
						 IP2LocationWebService {
       IP2LocationResponseTypeImpl IP2Location(IP2LocationTypeImpl input);
}
						
				
		
		 
		
				
						
								
										
这样一来我们就为
								ip2locationwebservice
								生成好了一个
								Java
								接口类,这个类将作为调用这个
								Web Service
								的客户端入口使用。
								
						
				
		
		
				
						
								
										
根据上面的介绍,我们可以根据同样的步骤为另一个
								Web Service
								:
								globalweather
								生成同样的
								SDO
								模型以及对应的
								Java
								接口:
								
										
										
								
						
				
		
		
				
						
								
										
								
						
				
		
		
				
						
								public
								 
								interface
						
				
				
						 WeatherProvider {
       GetCitiesByCountryResponseTypeImpl 
                      GetCitiesByCountry(GetCitiesByCountryTypeImpl input);
       GetWeatherResponseTypeImpl GetWeather(GetWeatherTypeImpl input);
}
						
				
		
		
				
 
		
				
						折腾了半天,想必各位看官已经有点烦了。
				
		
		
				
						
								
										
我这里解释一下,其实上面的这些步骤都是由于鄙人的
								Balto
								目前还没有完成
								WSDL2Java
								工具所致,只能由开发人员手动完成。假以时日,待
								Balto
								完成了
								WSDL2Java
								工具后,上述的这些操作讲统统不复存在,只需要开发人员通过生成向导,点几下即可完成上述的复杂工作。
								
						
				
		
		
				
						
								
										
完成
								SDO
								以及
								Java
								接口生成后,我们就可以添加
								SCA
								的
								ExternalService
								了。
						
				
		
		
				
						
								
										
首先,我们在这个
								Web Project
								的
								src
								下新建一个
								sca.module
								文件。
						
				
		
		
				
						
								
										
这个文件是必须存在的,只有它存在
								Balto
								才会认为这个
								Web porject
								是一个
								SCA
								模块,否则将不会对其进行处理。
						
				
		
		
				
						
								看一下
								sca.module
								文件:
						
				
		
		
		
		
				
						
								
								
								
										
										
								
						
				
		
		
				
						
						
						
						
								
										<?
										xml version="1.0" encoding="ASCII"
										?>
								
								
										
										
								
								
										<
										module 
										xmlns
										="http://www.osoa.org/xmlns/sca/0.9"
								
								
										
										
										    xmlns:v
								
								
										="http://www.osoa.org/xmlns/sca/values/0.9"
								
								
										
										
										    name
								
								
										="balto_weather_test"
										>
								
								
										
										
										    
								
								
										<
										externalService 
										name
										="IP2LocationWebService"
										>
								
								
										
										
										       
								
								
										<
										interface
										.java interface
										="com.fraudlabs.ws.client.IP2LocationWebService" />
								
										
										
										       
								
								
										<
										binding
										.ws port
								
								
										="http://ws.fraudlabs.com/ip2locationwebservice.asmx?wsdl
                    #wsdl.endpoint(Ip2LocationWebService/Ip2LocationWebServiceSoap)"
										/>
								
								
										
										
										    
								
								
										</
										externalService
										>
								
								
										
										
										    
								
								
										<
										externalService 
										name
										="WeatherProvider"
										>
								
								
										
										
										       
								
								
										<
										interface
										.java interface
										="net.x.webservice.client.WeatherProvider"
										/>
								
								
										
										
										       
								
								
										<
										binding
										.ws port
								
								
										="http://www.webservicex.net/globalweather.asmx?WSDL
                                 #wsdl.endpoint(GlobalWeather/GlobalWeatherSoap)"
										/>
								
								
										
										
										    
								
								
										</
										externalService
										>
								
								
										
										
								
								
										</
										module
										>
								
								
										
								
						
						
								
 
				
		
		
				
						我们定义了两个外部服务,一个是查询
						IP
						对应物理位置的,一个是通过物理位置查询天气情况的。
						
								
								
						
				
		
		
				
						现在我们可以直接使用它们。做一个测试使用的
						Servlet
						:
						
								
								
						
				
		
		
				
				
				
						
								
						
				
		
		
				
						
								public
								 
								class
								 IP2AreaTestServlet 
								extends
						
				
				
						
								 javax.servlet.http.HttpServlet{
       
								protected
								 
								void
						
				
				
						
								 doGet(HttpServletRequest request,
                     HttpServletResponse response) 
								throws
						
				
				
						
								 ServletException, 
                                                              IOException {
              String serverName 
								=
						
				
				
						
								 request.getServerName();
              String localName 
								=
						
				
				
						
								 request.getLocalName();
              
								//
								 获得访问者的IP地址
						
				
				
						
				
				
						
						              String remote 
				
				
						=
				
				
						
								 request.getRemoteAddr();
              
								//
								 找到Ip查询物理位置的外部服务
						
				
				
						
				
				
						
						              IP2LocationWebService service1 
				
				
						=
				
				
						
								 
                         (IP2LocationWebService) CurrentModuleContext.getContext().
                                                locateService(
								"
								IP2LocationWebService
								"
						
				
				
						
								);
              
								//
								 创建一个输入参数
						
				
				
						
				
				
						
						              IP2LocationType input 
				
				
						=
				
				
						
								 IP2LocationFactory.eINSTANCE
                            .createIP2LocationType();
              
								//
								 给出IP地址
						
				
				
						
				
				
						
						              input.setIP(remote);
              
				
				
						//
				
				
						
								 给一个License.这个License是该Web Service提供者给的一个免费版本的License,
              // 可能有使用次数限制
              
								//
								 如果大家想要一个新的,可以访问http:
								//
								www.fraudlabs.com 
						
				
				
						
				
				
						
						              input.setLICENSE(
				
				
						
								"
								02-L68K-D95T
								"
						
				
				
						
								);
              IP2LocationResponseTypeImpl result 
								=
						
				
				
						
								 service1
                            .IP2Location((IP2LocationTypeImpl) input);
              IP2LOCATION location 
								=
						
				
				
						
								 result.getIP2LocationResult();
              
								//
								 找到通过物理地址获得天气情况的外部服务
						
				
				
						
				
				
						
						              WeatherProvider provider 
				
				
						=
				
				
						
								 (WeatherProvider) CurrentModuleContext
                            .getContext().locateService(
								"
								WeatherProvider
								"
						
				
				
						
								);
              GetWeatherType i 
								=
						
				
				
						
								 WebserviceFactory.eINSTANCE.createGetWeatherType();
              i.setCityName(location.getCITY());
              i.setCountryName(location.getCOUNTRYNAME());
              String result2 
								=
						
				
				
						 provider.GetWeather((GetWeatherTypeImpl) i)  
                                                            .getGetWeatherResult();
              …….
       }
}
				
		
		
				
				 
		
		
				
						
								整个调用过程就是上面代码所示,获得的天气情况就是
								result2
								变量中所记录的。
						
				
		
		
				
						
								
										
这里说一下,
								IP2Location Web Service
								是需要
								License
								的,上面所填写的License是本人申请的一个,可能会有使用次数限制,如果大家需要可以去他们的网站注册一个。
						
				
		
		
				
						
								
										
在
								Servlet
								中获得
								Remote
								是远程的
								IP
								地址,如果这个
								Web Project
								是在内网中被访问,那得到的
								Remote
								地址就会是内网的
								IP
								,比如
								192.168.0.X
								,这样的
								IP
								地址不一定能查出来物理地址的,反正我测试的时候,得到的
								IP
								地址是
								168.1.100.X
								,对应的物理地址是瑞士的某个城市。
						
				
		
		
				
						
								
										
还有就是
								globalweather
								这个
								Web Service
								的返回结果很孙子,直接返回一个
								XML
								结构的字符串,还要我们自己解析,并且给出的
								encoding
								还有一些问题。
								
										
										
								
						
				
		
		
				
						
								
我对返回的值处理了一下,将结果打印了出来,访问这个
						Servlt
						后得到以下的结果:
						
								
								
						
				
		
		
				
				
		
		
				
						
								
						
						
								 
						
						
								
								
								
										小结
								
						
				
		
		
				
						
								在
								SCA
								中
								ExternalService 可以说是一个Module对外调用的接口,它可以屏蔽远程传送的差异性,只要给出正确的Binding,SCA容器就会成功调用远程的服务。ExternalService统一了SCA模块对外访问的方式,一个实现较好的SCA容器,将会支持多种Binding类型,比如EJB、JMS、RMI等,这样一来,在设计SCA程序的时候,只需要关心ExternalService的接口以及对应的数据结构,而那些如何去调用的技术细节将不会再困扰开发人员。
前段时间上网搜索一些关于SOA的资料,发现一个叫X极网的网站引用了我的<SCA程序设计——远程服务,以及远程服务实现的一些问题和想法>一文,特孙子,没有注明转载地址,还TM把标题给改了,鄙视一下!所以在这里我只想说:
                             转载注明原文地址,做人才厚道