分享

使用WSIF调用Web服务

 chanvy 2008-11-14

使用WSIF调用Web服务

级别: 初级

肖菁 (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的修改,不会影响到服务调用段代码的修改。

参考资料

1. apache的WSIF项目 http://ws./wsif/

2. apache的Axis项目 http://ws./axis/

工具下载地址:

1. WSIF 2.0 下载地址 http://www./dyn/closer.cgi/ws/wsif/

文中用到的类和WSDL文档、环境变量设置等请下载: WSIF-ejbbinding.rar

文中演示用到的Web服务的工程请大家下载: DefaultEAR.ear



关于作者

 

肖菁,联系方式: jing.xiao@chinacreator.com,目前是湖南省长沙铁道学院科创计算机系统集成有限公司软件中心软件工程师,IBM developerworks/BEA dev2dev撰稿人,主要研究J2EE编程技术、Web Service技术以及他们在websphere、weblogic、apache平台上的实现,拥有IBM 的 Developing With Websphere Studio证书。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多