Mrfei 发表于 2017-1-13 11:32:05

Apache CXF开发Web Service 理解CXF Frontends之Contract-First

《Apache CXF开发Web Service 理解CXFFrontends之Code-First》一文提到Code-First和Contract-First两种不同的方式,这里将介绍Contract-First的使用。如果使用Contract-First的开发方式,开发者首先准备好WSDL文档,通过CXF提供的工具wsdl2java来生成代码。这个工具在%CXF-HOME%/bin目录中。Contract-First需要完成的工作有:
 
生成服务组件
实现服务方法
发布Web Service
开发客户端
 
使用《Apache CXF开发WebService 理解CXF Frontends之Code-First》中生成的WSDL文档,即启动mvntest –Pserve后,访问http://localhost:8080/OrderProcess?wsdl所看到的内容。现在是要把操作倒过去,通过这个WSDL来生成SEI。
 
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="OrderProcessService"targetNamespace="http://order.demo/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http"xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"xmlns:tns="http://order.demo/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:types>
       <xs:schema attributeFormDefault="unqualified"elementFormDefault="unqualified" targetNamespace="http://order.demo/" xmlns:tns="http://order.demo/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
           <xs:element name="processOrder"type="tns:processOrder" />
           <xs:element name="processOrderResponse"type="tns:processOrderResponse" />
           <xs:complexType name="processOrder">
              <xs:sequence>
                  <xs:element minOccurs="0"name="arg0" type="tns:order"/>
              </xs:sequence>
           </xs:complexType>
           <xs:complexType name="order">
              <xs:sequence>
                  <xs:element minOccurs="0"name="customerID" type="xs:string" />
                  <xs:element minOccurs="0"name="itemID" type="xs:string"/>
                  <xs:element name="price"type="xs:double" />
                  <xs:element name="qty"type="xs:int" />
              </xs:sequence>
           </xs:complexType>
           <xs:complexType name="processOrderResponse">
              <xs:sequence>
                  <xs:element minOccurs="0"name="return" type="xs:string"/>
              </xs:sequence>
           </xs:complexType>
       </xs:schema>
    </wsdl:types>
    <wsdl:message name="processOrderResponse">
       <wsdl:part element="tns:processOrderResponse"name="parameters">
       </wsdl:part>
    </wsdl:message>
    <wsdl:message name="processOrder">
       <wsdl:part element="tns:processOrder"name="parameters">
       </wsdl:part>
    </wsdl:message>
    <wsdl:portType name="OrderProcess">
       <wsdl:operation name="processOrder">
           <wsdl:input message="tns:processOrder"name="processOrder">
           </wsdl:input>
           <wsdl:output message="tns:processOrderResponse"name="processOrderResponse">
           </wsdl:output>
       </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="OrderProcessServiceSoapBinding" type="tns:OrderProcess">
       <soap:binding style="document"transport="http://schemas.xmlsoap.org/soap/http"/>
       <wsdl:operation name="processOrder">
           <soap:operation soapAction="" style="document"/>
           <wsdl:input name="processOrder">
              <soap:body use="literal"/>
           </wsdl:input>
           <wsdl:output name="processOrderResponse">
              <soap:body use="literal"/>
           </wsdl:output>
       </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="OrderProcessService">
       <wsdl:port binding="tns:OrderProcessServiceSoapBinding"name="OrderProcessPort">
           <soap:address location="http://localhost:8080/OrderProcess"/>
       </wsdl:port>
    </wsdl:service>
</wsdl:definitions>
 
 
 
生成服务组件
 
将准备好的WSDL文档命名为OrderProcess.wsdl。文档的内容与使用JAX-WS规范的JAVA组件对应。
 
WSDLelement
Javacomponent
targetNamespaceattribute of the <wsdl:definitions> element
targetNamespace="http://order.demo/"
Java package(demo.order)
<wsdl:portType>
<wsdl:portType name="OrderProcess">
Java Service Endpoint Interface (SEI)
OrderProcess
<wsdl:operation>child element of the <wsdl:portType> element
<wsdl:operation name="processOrder">
Java methods
processOrder
<wsdl:service>
<wsdl:service name="OrderProcessService">
Service class
OrderProcessService
<wsdl:message>
Service operation parameters
 
关于wsdl2java工具的使用请参考:
http://cxf.apache.org/docs/wsdl-to-java.html
http://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html
 
这里将介绍Maven 的插件cxf-codegen-plugin 来生成代码的方式。《Apache CXF开发WebService 理解CXF Frontends之Code-First》文中提到的pom.xml添加cxf-codegen-plugin。
 
 
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>org.dcb.cxfbook.ch03</groupId>
    <artifactId>contractfirst</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
 
    <name>contractfirst</name>
    <url>http://maven.apache.org</url>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cxf.version>2.2.3</cxf.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>
    </dependencies>
   
    <build>
        <finalName>contractfirst</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>${cxf.version}</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>src/main/resources/OrderProcess.wsdl</wsdl>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
   
    <profiles>
        <profile>
            <id>server</id>
            <build>
                <defaultGoal>test</defaultGoal>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <phase>test</phase>
                                <goals>
                                    <goal>java</goal>
                                </goals>
                                <configuration>
                                    <mainClass>demo.order.OrderProcessServer</mainClass>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>client</id>
            <build>
                <defaultGoal>test</defaultGoal>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <phase>test</phase>
                                <goals>
                                    <goal>java</goal>
                                </goals>
                                <configuration>
                                    <mainClass>demo.order.client.Client</mainClass>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>
 
 
执行命令:
 
cd contractfirst
mvn generate-sources
 
Maven cxf-codegen-plugin会为你自动调用CXF 中wsdl2java工具。可能初学Maven的朋友不大理解,这里简单介绍cxf-codegen-plugin的使用。在build.plugins.plugin中添加cxf-codegen-plugin。<wsdl>src/main/resources/OrderProcess.wsdl</wsdl>指明要转换的WSDL文档。<phase>generate-sources</phase>指明执行的命令。<goal>wsdl2java</goal>指明执行命令所包含的工作。
 
对于Goal和Phase的关系,在《Maven中的几个重要概念(二):lifecycle, phase and goal》一文中有详细的介绍。这里摘选Goal和Phase的内容:
 
Maven定义了一系列Best Practice,将关联的Phase组合在一起,即执行一个phase会执行某个liefcycle所有的phase。Goal是独立的,可以绑定到多个phase中,也可以不绑定。从这方面讲,phase就是goal的容器,实际被执行的是goal。
 
在本文中执行generate-sources这个phase,其实是执行cxf-codegen-plugin中的<goal>wsdl2java</goal>
 
对于Maven的生命周期,请看《Maven生命周期详解》。
 
跑题了半天,让我们看看这mvn generate-sources到底生成了什么内容:
JAXB输入/输出消息类。wsdl2java类会分别生成JAVA输入/输出消息组件。本例中将会生成ProcessOrder作为输入类,生成ProcessOrderResponse作为输出类,还会根据<xs:complexType name="order">生成Order类。
服务接口。本例中服务接口为OrderProcess。
服务实现类。本例中提供了继承自Service接口的实现类OrderProcessService。我们可以修改这个类来实现功能。
 
这些类都在包demo.order中。wsdl2java工具从targetNamespace="http://order.demo/"生成包名,也就是http://order.demo/除去http://后倒写。
 
如果修改pom.xml,添加如下内容,将会生成OrderProcessImpl.java(示例的实现服务类)和OrderProcess_OrderProcessPort_Server.java(CXF提供的独立的服务器)。
                            <wsdlOption>
                                <wsdl>src/main/resources/OrderProcess.wsdl</wsdl>
                                <extraargs>
                                   <extraarg>-server</extraarg>
                                   <extraarg>-impl</extraarg>
                                   <extraarg>-verbose</extraarg>
                                </extraargs>
                            </wsdlOption>
 
 
 
JAXB输入/输出消息类
 
ProcessOrder, ProcessOrderResponse和Order这三个类代表WebService操作类。这几个类有着各种JAXB注解。ProcessOrder和ProcessOrderResponse用来表示Request和Response。Request拥有出入参数引用,而Response着拥有输出参数引用。
 
为了理解Request和Response的概念,来看看Web Service将会提交什么样的SOAP Request消息。
 
<soap:Envelopexmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
     <ns2:processOrderxmlns:ns2="http://order.demo/">
        <arg0>
           <customerID>C001</customerID>
           <itemID>I001</itemID>
           <price>200.0</price>
           <qty>100</qty>
        </arg0>
     </ns2:processOrder>
</soap:Body>
</soap:Envelope>
 
processOrder映射为WebService中的方法processOrder。子元素arg0代表着SOAP payload,映射为输入参数Order。CXF会自动将arg0转换为Order对象,并执行processOrder方法。
 
 
 
服务接口
 
OrderProcess是SEI,定义了processOrder方法。
 
@WebService(targetNamespace = "http://order.demo/", name = "OrderProcess")
@XmlSeeAlso({ObjectFactory.class})
public interface OrderProcess {
 
    @WebResult(name = "return", targetNamespace ="")
    @RequestWrapper(localName = "processOrder", targetNamespace ="http://order.demo/", className = "demo.order.ProcessOrder")
    @ResponseWrapper(localName = "processOrderResponse",targetNamespace = "http://order.demo/", className = "demo.order.ProcessOrderResponse")
    @WebMethod
    public java.lang.String processOrder(
        @WebParam(name = "arg0", targetNamespace ="")
        demo.order.Order arg0
    );
}
 
@WebService定义了这个接口是SEI。
@Xml SeeAlso通知JAXB在执行数据绑定是包含ObjectFactory。
@RequestWrapper包含了输入消息。
@ResponseWrapper包含了输出消息。
@WebResult指明返回的类型。
@WebMethod指明这是个服务方法。
@WebParam指明参数。
 
 
 
运行Web Service
 
《Apache CXF开发Web Service 理解CXFFrontends之Code-First》一文执行过程类似。
 
cd contractfirst
#启动server,显示Serverready...消息
mvn test–Pserver
#执行client,显示The orderID is ORD1234
mvn test -Pclient
 
 
 
参考内容
 
《Maven中的几个重要概念(二):lifecycle, phase and goal》
《Maven生命周期详解》
http://cxf.apache.org/docs/wsdl-to-java.html
http://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
页: [1]
查看完整版本: Apache CXF开发Web Service 理解CXF Frontends之Contract-First