级别: 初级
肖菁 (jing.xiao@chinacreator.com), 软件工程师, 湖南省长沙铁道学院科创计算机系统集成有限公司软件中心
2004 年 1 月 01 日
WSIF中允许客户端实现者不使用传统的RPC方法调用web服务,而是使用基于WSDL文件的调用方法来调用Web服务,这样服务器端实现方法的更改不会影响到客户端代码的修改,而是将所有的修改现在在被使用的WSDL文件中,很大程度简化了程序员的工作。详细的介绍请大家参考作者的另一篇文章《WSIF简介》。本文中作者将重点描述如何使用WSIF提供的WSDL扩展将来调用已经被发布的Web服务。
1 使用WSAD 5发布一个Web服务
在开始我们的调用工作之前,我们需要准备好一个已经被发布的Web服务,考虑到简单性,我们选择自己创建一个简单的Web服务并且发布到WSAD5的测试服务器上。
1.1 使用WSAD创建一个Web服务
首先我们需要创建一个Web服务,我们的演示实例是从一个java类创建的Web服务,这个服务的业务逻辑很简单,就是根据传入的参数返回"Say Hello To :%参数%" ;该Java类的源代码如下:
package mows;
public class HelloWorld {
public String getString(String param){
return "say hello to : " + param;
}
}
|
至于如何从该java类生成Web服务,请大家参考IBM developerWorks上的其它相关文章,作者这里不在多作解释。
1.2 Web服务发布
web服务创建成功以后,我们可以将他发布到WSAD5的测试服务器上,然后使用WSAD5自动创建的客户端访问该web服务,确保该Web服务已经正常发布和可以正常工作。
好了,现在给大家演示一个例子,看看如何在应用中使用WSIF的统一调用方法进行调用这个Web服务。
2 WSIF调用实例
2.1 如何编写WSDL文档
在WSAD5中,发布该服务的时侯会自动生成四个WSDL文档:HelloWorld.wsdl,HelloWorldBinding.wsdl,HelloWorldService.wsdl,HelloWorldJava.wsdl。其中我们需要用到的是前面三个文件,下面是生成我们需要的WSDL文档的详细过程:
- 将HelloWorld.wsdl复制另存为SoapWsdl.wsdl
- 将HelloWorldBinding.wsdl的binding子元素拷贝到SoapWsdl.wsdl文件中成为definitions元素的子元素
- 将HelloWorldService.wsdl文件中的service子元素拷贝到SoapWsdl.wsdl文件中成为definitions元素的子元素
- 在SoapWsdl.wsdl增加HelloWorldBinding.wsdl中关于SOAP命名空间的定义
- 在SoapWsdl.wsdl增加HelloWorldBinding.wsdl中关于interface命名空间的定义
- 将SoapWsdl.wsdl中port的binding属性由binding:HelloWorldBinding改为interface:HelloWorldBinding
好了,现在我们就可以通过这个SoapWsdl文件来访问这个Web服务了。
[注] 使用其它工具发布Web服务和自动生成的WSDL文档的方式和WSAD5不完全相同,所以我们编写调用Web服务的WSDL文档的方法也不一样,但是大家可以参考这个过程。
2.2 使用WSIF提供的API调用
好了,现在我们已经编写好了调用该Web服务的WSDL文档了,接下来的工作将是演示如何使用WSIF提供的API通过使用我们编写的WSDL文档来调用这个服务。
下面这段代码是作者使用的调用该服务的Run.java, 供大家参考。它需要我们的WSDL文件名作为参数,处理结果是将服务调用的返回结果打印在控制台上。
//Run.java
package dynamic;
import javax.xml.namespace.QName;
import org.apache.wsif.WSIFMessage;
import org.apache.wsif.WSIFOperation;
import org.apache.wsif.WSIFPort;
import org.apache.wsif.WSIFService;
import org.apache.wsif.WSIFServiceFactory;
public class Run {
public static void main(String[] args) throws Exception {
// 第一个参数是 WSDL文件的位置和名字
// 创建服务工厂(service factory)
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
WSIFService service =
factory.getService(
args[0],
null,
null,
"http://dl/HelloWorld/",
"HelloWorld");
// 参数http://dl/HelloWorld/对应于我们WSDL文档中的targetNamespace
//参数HelloWorld对应于WSDL文档中的porttype
// 参数类型映射
service.mapType(
new QName("http://wsifservice.helloworld", "param"),
Class.forName(
"java.lang.String"));
// 获得port
WSIFPort port = service.getPort();
// 创建操作(operation)
WSIFOperation operation = port.createOperation("getHelloString");
// 创建和该操作调用相关的输入/输出/错误信息
WSIFMessage input = operation.createInputMessage();
WSIFMessage output = operation.createOutputMessage();
WSIFMessage fault = operation.createFaultMessage();
// 组装输入信息
input.setObjectPart("param", "xiaojing");
// 执行调用
if (operation.executeRequestResponseOperation(input, output, fault)) {
// 调用成功,从返回信息中获取我们需要的信息
// message
String zipInfo =
(String) output.getObjectPart("result");
// result就是我们的WSDL文档中的output对应的消息(message元素)中的参数(part元素)的名字
System.out.println(zipInfo);
} else {
System.out.println("Invocation failed");
// 调用失败,处理错误信息
}
}
}
|
如果大家看过作者的另外两篇文章《使用WSIF调用本地java类》和《使用WSIF调用EJB》,你就会发现他们使用的调用代码实际上是一模一样的,除了输入的WSDL文件名不同和一些服务相关的参数外。这也是WSIF的重要特性:
- 通过WSDL文件调用服务,不管他是如何实现和被访问的。
- 尽可能的将修改限制在WSDL文件中而不需要修改应用代码
2.3 编译运行
2.3.1 设置环境变量
由于编译和运行这个程序需要将大量的.jar文件设置到classpath中,所以请各位参考下载的WSIF包中的classpath.bat和lcp.bat编写自己的脚本来实现环境变量的设置。后面的下载的包里面有作者编写的环境变量设置脚本,供大家参考。
2.3.2 运行
设置好环境变量后,编译程序,然后就可以使用下面的命令来执行这个程序了:
java dynamic.Run EJBWsdl.wsdl
|
它执行后的显示结果如下图:
2.4 可改进的地方
如果各位有心的话,应该可以发现,其实我们编写的Run.java中的有些参数仍然来自于我们的WSDL文档、和客户应用基本没有关联(比如:factory.getService方法调用的第四个参数和第五个参数,他们来源于WSDL中的一些元素,而且和客户应用基本没有关联),所以如果你可以做的话,你可以自己编写一个基于SAX的XML文档解析类,将这些和WSDL关联而和应用代码不很密切的内容从WSDL中直接取值,而不是依赖于编程者的输入。
3 复杂类型
如果被输入的参数或者返回的参数不是java的原始类型,那么我们的类型映射就没有这么简单了。大家可以参考WSIF中提供的localjava的例子,它的返回类型都用到了 一个address的类型,它是该实例中用到的一个自定义的类型,对应于一个java类,WSDL文档的编写也和一般的不同,请参考WSIF中提供的AddressBook.wsdl实例。不过一点可以给大家提示的是,编写好了wsdl文档后,其中复杂类型对应的java类不需要自己编写,可以使用Axis提供的wsdl2java功能来生成,命令的使用类似于:java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL),详细的帮助请大家参考Axis项目的用户指导(User Guide)
4 总结
WSIF允许使用者通过WSDL文件直接调用web服务,而不是使用传统的RPC调用方法,这样做的好处就是当服务器端实现代码和实现方式发生改变时,尽可能的减少对客户端代码的影响,而将这种影响限制在对WSDL文档的修改工作中。
本文中作者详细的介绍如何使用WSIF调用Web服务的过程,给出了编写WSDL文档的实例和简单的说明,同时给出了如何通过WSIF提供的统一的调用方式通过WSDL文档调用Web服务的例子。通过实例大家可以看到我们实现了服务调用和服务实现的分离,任何服务实现和相关的映射基本上只会影响到服务的实现和WSDL的修改,不会影响到服务调用段代码的修改。
|