`

CXF入门教程(3) -- webService客户端开发步骤详解

 
阅读更多
原文参考:http://blog.csdn.net/neareast/article/details/7724662
教程(2)依据教程(1)中提供的WSDL契约,对其发布的webService创建了一个简单的客户端;本文详细介绍一下webService客户端开发的一般步骤。
生成Stub代码
在CXF中,开发一个service消费者(或客户端)的起点是一个WSDL契约,连同端口类型、绑定以及service定义。然后我们就可以使用 wsdl2java 工具来根据WSDL契约生成Java stub 代码。stub代码提供了调用远端服务方法所需的支持代码。
wsdl2java 工具可以为CXF客户端生成下列代码:
Stub code - 实现一个CXF客户端需要的支持文件。
Client starting point code - 样例客户端代码,可以连到远程服务并调用每一个操作。
Ant build file - 一个ant构建工具可以使用的 build.xml 文件,其中包含构建和运行样例程序的targets。

基本的 HelloWorld WSDL 契约
下面是HelloWorld WSDL 契约的示例。该契约定义了一个单一的端口类型,Greeter;一个SOAP绑定,Greater_SOAPBinding;以及一个服务,SOAPService,它有一个单独的端口,SoapPort。
HelloWorld WSDL Contract
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http"
 
    xmlns="http://schemas.xmlsoap.org/wsdl/"
 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
 
    xmlns:tns="http://apache.org/hello_world_soap_http"

     xmlns:x1="http://apache.org/hello_world_soap_http/types"

     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <wsdl:types>
        <schema targetNamespace="http://apache.org/hello_world_soap_http/types"
 
           xmlns="http://www.w3.org/2001/XMLSchema"

	    xmlns:tns="http://apache.org/hello_world_soap_http/types"

            elementFormDefault="qualified">
	    <simpleType name="MyStringType">
		<restriction base="string">
		    <maxLength value="30" />
		</restriction>
	    </simpleType>

            <element name="sayHi">
                <complexType/>
            </element>
            <element name="sayHiResponse">
                <complexType>
                    <sequence>
                        <element name="responseType" type="string"/>
                    </sequence>
                </complexType>
            </element>
            <element name="greetMe">
                <complexType>
                    <sequence>
                        <element name="requestType" type="tns:MyStringType"/>
                    </sequence>
                </complexType>
            </element>
            <element name="greetMeResponse">
                <complexType>
                    <sequence>
                        <element name="responseType" type="string"/>
                    </sequence>
                </complexType>
            </element>
            <element name="greetMeOneWay">
                <complexType>
                    <sequence>
                        <element name="requestType" type="string"/>
                    </sequence>
                </complexType>
            </element>
            <element name="pingMe">
                <complexType/>
            </element>
            <element name="pingMeResponse">
                <complexType/>
            </element>
            <element name="faultDetail">
                <complexType>
                    <sequence>
                        <element name="minor" type="short"/>
                        <element name="major" type="short"/>
                    </sequence>
                </complexType>
            </element>
        </schema>
    </wsdl:types>
    <wsdl:message name="sayHiRequest">
        <wsdl:part element="x1:sayHi" name="in"/>
    </wsdl:message>
    <wsdl:message name="sayHiResponse">
        <wsdl:part element="x1:sayHiResponse" name="out"/>
    </wsdl:message>
    <wsdl:message name="greetMeRequest">
        <wsdl:part element="x1:greetMe" name="in"/>
    </wsdl:message>
    <wsdl:message name="greetMeResponse">
        <wsdl:part element="x1:greetMeResponse" name="out"/>
    </wsdl:message>
    <wsdl:message name="greetMeOneWayRequest">
        <wsdl:part element="x1:greetMeOneWay" name="in"/>
    </wsdl:message>
    <wsdl:message name="pingMeRequest">
        <wsdl:part name="in" element="x1:pingMe"/>
    </wsdl:message>
    <wsdl:message name="pingMeResponse">
        <wsdl:part name="out" element="x1:pingMeResponse"/>
    </wsdl:message>		
    <wsdl:message name="pingMeFault">
        <wsdl:part name="faultDetail" element="x1:faultDetail"/>
    </wsdl:message>
    
    <wsdl:portType name="Greeter">
        <wsdl:operation name="sayHi">
            <wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/>
            <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/>
        </wsdl:operation>
        
        <wsdl:operation name="greetMe">
            <wsdl:input message="tns:greetMeRequest" name="greetMeRequest"/>
            <wsdl:output message="tns:greetMeResponse" name="greetMeResponse"/>
        </wsdl:operation>
        
        <wsdl:operation name="greetMeOneWay">
            <wsdl:input message="tns:greetMeOneWayRequest" 
                name="greetMeOneWayRequest"/>
        </wsdl:operation>

        <wsdl:operation name="pingMe">
            <wsdl:input name="pingMeRequest" message="tns:pingMeRequest"/>
            <wsdl:output name="pingMeResponse" message="tns:pingMeResponse"/>
            <wsdl:fault name="pingMeFault" message="tns:pingMeFault"/>
        </wsdl:operation> 
    </wsdl:portType>
    <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
        <soap:binding style="document" 
             transport="http://schemas.xmlsoap.org/soap/http"/>
        
        <wsdl:operation name="sayHi">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="sayHiRequest">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="sayHiResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
        
        <wsdl:operation name="greetMe">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="greetMeRequest">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="greetMeResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
        
        <wsdl:operation name="greetMeOneWay">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="greetMeOneWayRequest">
                <soap:body use="literal"/>
            </wsdl:input>
        </wsdl:operation>

        <wsdl:operation name="pingMe">
            <soap:operation style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
            <wsdl:fault name="pingMeFault">
                <soap:fault name="pingMeFault" use="literal"/>
            </wsdl:fault>
        </wsdl:operation>
        
    </wsdl:binding>
    <wsdl:service name="SOAPService">
        <wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort">
            <soap:address 
                location="http://localhost:9000/SoapContext/SoapPort"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

Greeter 端口类型定义了下列WSDL 操作:sayHi - 有一个输出参数,类型是 xsd:string。
greetMe - 有一个 xsd:string 类型的输入参数,以及一个 xsd:string 类型的输出参数。
greetMeOneWay -  有一个 xsd:string 类型的输入参数 。因为这个操作没有输出参数,CXF可以将其优化为一个单向的调用(也就是说,客户端不等待服务器的响应)。
pingMe - 没有输入输出参数,但是可以引起一个错误异常。

该WSDL还为SOAP协议定义了一个绑定。实际上,这个绑定通常是自动生成的 —— 例如,通过执行CXF wsdl2soap 或 wsdl2xml 工具。同样,SOAPService 可以通过执行CXF的wsdl2service工具自动生成。

生成 stub 代码
有了WSDL契约之后,我们可以用CXF的wsdl2java工具来生成客户端代码。在命令行提示符下输入类似下面这样的命令:

wsdl2java -ant -client -d D:/temp -p com.neareast.test.cxf.client.WSDL2Java -frontend jaxws21 hello_world.wsdl

最后的 hello_world.wsdl 是一个包含上述WSDL契约的文件,(也可以指定一个服务的URL地址)。其他参数均为常用的可选参数,各参数的作用为:

-ant 指定要生成一个ant的构建说明文档build.xml。
-client 指定要生成一个测试客户端的“起点代码”(starting point code),其中包含了端口中所有方法的测试样例代码。
-d 指定我们想要把生成的文件放到哪个目录下,默认是wsdl2Java命令所在的目录。
-p 指定生成文件的包名;默认是根据WSDL文件中的命名空间相对应。
-frontend 指定前端类型及版本;目前仅支持 JAXWS 前端,用 "jaxws21" 表明要生成JAX-WS 2.1 兼容的代码(Jre6自带的就是这个版本),使用该参数的原因请参考教程(2)。
如果没有用-p参数指定包名,上面的命令会生成下面两个包:

org.apache.hello_world_soap_http
这个包是根据 http://apache.org/hello_world_soap_http 目标命名空间生成的。该命名空间下的所有WSDL实体(例如 Greeter 端口类型和 SOAPService 服务)都被映射到相应的Java包中。
org.apache.hello_world_soap_http.types
这个包是根据 http://apache.org/hello_world_soap_http/types 目标命名空间生成的。该命名空间下的所有XML类型(也就是HelloWorld契约下wsdl:types元素中定义一切) 都被映射到相应的Java包中。
wsdl2java 命令生成的 stub 文件分成下列类型:

代表WSDL实体的类 (在 org.apache.hello_world_soap_http 包中):
Greeter 一个可以表示Greater WSDL端口类型的Java接口。在 JAX-WS 术语中,这个Java接口被称为一个服务端点接口(service endpoint interface),简称SEI。
SOAPService 一个代表WSDL service元素的类 SOAPService。
PingMeFault 一个Java异常类(扩展了java.lang.Exception类),代表WSDL fault 元素 pingMeFault。
代表XML类型的类 (在 org.apache.hello_world_soap_http.types 包中) - 在 HelloWorld 例子中,所谓的类型就是请求和应答消息的各种包装器,其中一些类型会在异步调用模式中用到。


实现一个CXF客户端
这一章节描述了如何基于上述的WSDL契约,来写一个简单的Java客户端。要实现客户端,我们需要使用以下 stub 类:
Service class 服务类,(也就是SOAPService)。
Service endpoint interface 服务端点接口(也就是 Greeter)。


生成的服务类
下面是生成名为的服务类的一个典型的轮廓,我们暂且叫它ServiceName类,可以看到它扩展了javax.xml.ws.Service 基类。

Outline of a Generated Service Class
public class ServiceName extends javax.xml.ws.Service
{
  ...
  public ServiceName(URL wsdlLocation, QName serviceName) { }
  
  public ServiceName() { }

  public Greeter getPortName() { }
  .
  .
  .
}

ServiceName 类定义了如下方法:

构造方法 - 有如下两种形式的构造方法:
ServiceName(URL wsdlLocation, QName serviceName) 基于WSDL契约中serviceName 服务的数据,构造一个服务对象;这个WSDL契约是从wsdlLocation 获得的。
ServiceName() 这是默认的构造器,基于stub代码生成时(例如,运行CeltiXfire wsdl2java时)提供的服务名和WSDL契约来构造服务对象。使用这个构造器的前提是,原始位置的WSDL契约仍然可用。
get_PortName_() 方法- 针对ServiceName 服务中定义的每一个PortName端口,CXF都会生成对应的get_PortName_()方法。所以,一个定义了多个端口的wsdl:service 元素会生成一个包含多个get_PortName_()方法的服务类。


服务端点接口
对于原始的WSDL契约中定义的每一个端口类型,我们都可以生成对应的服务端点接口Java代码。一个服务端点接口就是一个WSDL端口类型的Java映射。原始WSDL端口类型中定义的每一个操作都映射为服务端点接口中对应的一个方法。操作的参数的映射规则如下:

输入参数被映射为方法的参数。
第一个输出参数被映射为一个返回值。
如果有多于一个的输出参数,第二个以及其后的输出参数映射为方法的参数(值得一提的是,这些参数的值必须使用Holder类型进行传递)。
例如,下面展示的是Greeter服务端点接口,它是由前面的WSDL契约中定义的Greeter端口类型生成的。为简单起见,下面的例子省略了标准的JAXB 及 JAX-WS 注解。

The Greeter Service Endpoint Interface
/* Generated by WSDLToJava Compiler. */

package org.objectweb.hello_world_soap_http;
  ...
public interface Greeter
{
  public java.lang.String sayHi();
  
  public java.lang.String greetMe(java.lang.String requestType);

  public void greetMeOneWay(java.lang.String requestType);

  public void pingMe() throws PingMeFault;
}



客户端 main 函数
下面是实现了简单客户端的Java代码。简要地说,客户端连接到SOAPService 服务的SoapPort 端口,然后调用Greeter 端口类型支持的每一个操作。

Client Implementation Code
package demo.hw.client;

import java.io.File;
import java.net.URL;
import javax.xml.namespace.QName;
import org.apache.hello_world_soap_http.Greeter;
import org.apache.hello_world_soap_http.PingMeFault;
import org.apche.hello_world_soap_http.SOAPService;

public final class Client {

  private static final QName SERVICE_NAME = 
    new QName("http://apache.org/hello_world_soap_http", 
    "SOAPService");

  private Client()
  {
  }

  public static void main(String args[]) throws Exception
  {
    if (args.length == 0)
    {
      System.out.println("please specify wsdl");
      System.exit(1);
    }

    URL wsdlURL;
    File wsdlFile = new File(args[0]);
    if (wsdlFile.exists())
    {
      wsdlURL = wsdlFile.toURL();
    }
    else
    {
      wsdlURL = new URL(args[0]);
    }

    System.out.println(wsdlURL);
    SOAPService ss = new SOAPService(wsdlURL, SERVICE_NAME);
    Greeter port = ss.getSoapPort();
    String resp;

    System.out.println("Invoking sayHi...");
    resp = port.sayHi();
    System.out.println("Server responded with: " + resp);
    System.out.println();

    System.out.println("Invoking greetMe...");
    resp = port.greetMe(System.getProperty("user.name"));
    System.out.println("Server responded with: " + resp);
    System.out.println();

    System.out.println("Invoking greetMeOneWay...");
    port.greetMeOneWay(System.getProperty("user.name"));
    System.out.println("No response from server as method is OneWay");
    System.out.println();

    try {
      System.out.println("Invoking pingMe, expecting exception...");
      port.pingMe();
    } catch (PingMeFault ex) {
      System.out.println("Expected exception: PingMeFault has occurred.");
      System.out.println(ex.toString());
    }
    System.exit(0);
  }
} 

Client.main()函数的执行过程如下:

CXF运行时被隐式地初始化 —— 也就是说,假定CXF运行时类被加载了。因此,没必要调用一个特殊的函数来初始化CXF。
客户端有一个预期的字符串参数,用来给出WSDL契约的地址;该地址被保存在wsdlURL变量中。
为了能够访问远程的服务端点,我们创建一个新的端口对象;下面的代码片段展示了创建该对象的两个步骤:
SOAPService ss = new SOAPService(wsdlURL, SERVICE_NAME);
Greeter port = ss.getSoapPort();

要创建一个新的端口对象,我们先创建一个服务对象(传入WSDL地址以及服务名这两个参数),然后调用合适的getPortName() 方法来获取我们需要的特定的端口的实例。本例中,SOAPService 服务仅支持SoapPort端口,也就是 Greeter类型。

接下来,客户端调用Greeter服务端点接口支持的每一个方法。
调用pingMe() 操作的实例中,展示了如何捕获PingMeFault 错误异常。
参考文档:http://cxf.apache.org/docs/developing-a-consumer.html
分享到:
评论

相关推荐

    cxf 开发webservice客户端

    &lt;artifactId&gt;cxf-rt-frontend-jaxws &lt;version&gt;3.4.x &lt;groupId&gt;org.apache.cxf &lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt; &lt;version&gt;3.4.x ``` 请替换`3.4.x`为最新的CXF版本。 2. 生成客户端代码:...

    CXF入门 -- 简单客户端示例

    CXF入门教程(2) -- 简单客户端示例文章附带代码,为使用方便,将service和client代码合并到一个工程中。原文地址http://blog.csdn.net/neareast/article/details/7717568

    使用cxf wsdl2java生成webservice客户端

    使用cxf wsdl2java生成webservice客户端命令

    CXF入门教程(4) -- webService异步调用模式

    CXF入门教程(4) -- webService异步调用模式文章配套代码,文中涉及的异步调用客户端的代码放在com.neareast.test.cxf.asyClient包下。原文地址:http://blog.csdn.net/neareast/article/details/7726503

    cxf-rt-rs-client-3.0.1-API文档-中文版.zip

    赠送jar包:cxf-rt-rs-client-3.0.1.jar; 赠送原API文档:cxf-rt-rs-client-3.0.1-javadoc.jar; 赠送源代码:cxf-rt-rs-client-3.0.1-sources.jar; 赠送Maven依赖信息文件:cxf-rt-rs-client-3.0.1.pom; 包含...

    apache-cxf-2.7.7以及cxf客户端所需要的jar包

    这个压缩包"apache-cxf-2.7.7以及cxf客户端所需要的jar包"包含了Apache CXF 2.7.7版本及其客户端运行所需的库文件。这些jar包对于创建、部署和消费Web服务至关重要,特别是对于使用命令行生成Web服务客户端的开发者...

    CXF入门 -- 第一个简单webService

    【CXF入门 -- 第一个简单webService】 Apache CXF 是一款强大的开源服务框架,它用于构建和开发服务,包括Web服务。本篇文章将带你入门CXF,通过创建一个简单的Web服务来理解其基本概念和工作流程。 1. **CXF简介*...

    cxf-rt-frontend-jaxrs-3.0.1-API文档-中文版.zip

    赠送jar包:cxf-rt-frontend-jaxrs-3.0.1.jar; 赠送原API文档:cxf-rt-frontend-jaxrs-3.0.1-javadoc.jar; 赠送源代码:cxf-rt-frontend-jaxrs-3.0.1-sources.jar; 赠送Maven依赖信息文件:cxf-rt-frontend-jaxrs...

    cxf-rt-transports-http-3.0.1-API文档-中文版.zip

    赠送jar包:cxf-rt-transports-http-3.0.1.jar; 赠送原API文档:cxf-rt-transports-http-3.0.1-javadoc.jar; 赠送源代码:cxf-rt-transports-http-3.0.1-sources.jar; 赠送Maven依赖信息文件:cxf-rt-transports-...

    cxf-rt-frontend-simple-3.0.1-API文档-中文版.zip

    赠送jar包:cxf-rt-frontend-simple-3.0.1.jar; 赠送原API文档:cxf-rt-frontend-simple-3.0.1-javadoc.jar; 赠送源代码:cxf-rt-frontend-simple-3.0.1-sources.jar; 赠送Maven依赖信息文件:cxf-rt-frontend-...

    cxf-rt-frontend-jaxws-3.0.1-API文档-中文版.zip

    赠送jar包:cxf-rt-frontend-jaxws-3.0.1.jar; 赠送原API文档:cxf-rt-frontend-jaxws-3.0.1-javadoc.jar; 赠送源代码:cxf-rt-frontend-jaxws-3.0.1-sources.jar; 赠送Maven依赖信息文件:cxf-rt-frontend-jaxws...

    springboot整合CXF发布webservice和客户端调用

    SpringBoot整合CXF是将流行的Java Web服务框架CXF与SpringBoot轻量级框架结合,以便更方便地创建和消费Web服务。这个项目提供了一个很好的示例,通过详细注释帮助开发者理解如何在SpringBoot应用中发布和调用Web服务...

    使用CXF和camel-cxf调用webservice

    3. **调用服务**:一旦客户端准备好,就可以通过CXF客户端API来调用服务方法,传递必要的参数并接收响应。 Apache Camel 是一个强大的集成框架,它提供了一种声明式的方式来定义和路由消息流。camel-cxf是Camel的一...

    cxf-rt-bindings-soap-3.0.1-API文档-中文版.zip

    赠送jar包:cxf-rt-bindings-soap-3.0.1.jar; 赠送原API文档:cxf-rt-bindings-soap-3.0.1-javadoc.jar; 赠送源代码:cxf-rt-bindings-soap-3.0.1-sources.jar; 赠送Maven依赖信息文件:cxf-rt-bindings-soap-...

    WebService开发客户端 cxf方式

    二、WebService客户端开发步骤 1. **理解WSDL**:首先,你需要获取服务的WSDL文档,它是WebService接口的定义,描述了服务的端点、消息结构和操作。 2. **生成客户端代码**:使用CXF的wsdl2java工具,可以基于WSDL...

    05-ApacheCamel-CXF-WebService

    在项目中,"05-ApacheCamel-CXF-WebService-Client"这部分内容可能是客户端的应用,用于调用由Apache CXF和Camel服务端提供的Web服务。客户端通常包括CXF的客户端API配置,以及Camel的路由定义,用于发起服务请求并...

    cxf-core-3.0.1-API文档-中文版.zip

    赠送jar包:cxf-core-3.0.1.jar; 赠送原API文档:cxf-core-3.0.1-javadoc.jar; 赠送源代码:cxf-core-3.0.1-sources.jar; 赠送Maven依赖信息文件:cxf-core-3.0.1.pom; 包含翻译后的API文档:cxf-core-3.0.1-...

    CXF 一个完整的webService(整合客户端和服务端)

    在CXF中,服务端的开发通常涉及以下步骤: 1. 定义服务接口:使用Java接口定义服务方法。 2. 实现服务接口:编写具体的业务逻辑。 3. 创建WSDL:CXF可以通过接口自动生成WSDL,或者手动编写。 4. 发布服务:使用CXF...

    使用cxf和spring开发基于https的webservice服务端以及客户端样例

    客户端开发相对简单,它通过CXF的WSClientAPI动态生成代理对象,调用远程服务。首先,我们需要设置HTTPS的信任管理器,信任服务端的证书。然后,通过JAX-WS的`Service`类和WSDL URL创建服务代理,并获取业务接口的...

    WebService CXF 详细教程

    **WebService CXF 详解** **一、WebService简介** WebService是一种基于标准的,可以在不同操作系统、编程语言之间交换数据的Web应用程序。它通过WSDL(Web服务描述语言)定义了服务接口,利用SOAP(简单对象访问...

Global site tag (gtag.js) - Google Analytics