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

Apache CXF开发Web Service 理解CXF FrontendsCode-First》一文提到Code-FirstContract-First两种不同的方式,这里将介绍Contract-First的使用。如果使用Contract-First的开发方式,开发者首先准备好WSDL文档,通过CXF提供的工具wsdl2java来生成代码。这个工具在%CXF-HOME%/bin目录中。Contract-First需要完成的工作有:

 

生成服务组件

实现服务方法

发布Web Service

开发客户端

 

使用《Apache CXF开发Web Service 理解CXF FrontendsCode-First》中生成的WSDL文档,即启动mvn test –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组件对应。

 

WSDL element

Java component

targetNamespace attribute of the <wsdl:definitions>  element

targetNamespace="http://order.demo/"

Java packagedemo.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开发Web Service 理解CXF FrontendsCode-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.0 http://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>指明执行命令所包含的工作。

 

对于GoalPhase的关系,在《Maven中的几个重要概念()lifecycle, phase and goal》一文中有详细的介绍。这里摘选GoalPhase的内容:

 

Maven定义了一系列Best Practice,将关联的Phase组合在一起,即执行一个phase会执行某个liefcycle所有的phaseGoal是独立的,可以绑定到多个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.javaCXF提供的独立的服务器)。

                            <wsdlOption>

                                <wsdl>src/main/resources/OrderProcess.wsdl</wsdl>

                                <extraargs>

                                   <extraarg>-server</extraarg>

                                   <extraarg>-impl</extraarg>

                                   <extraarg>-verbose</extraarg>

                                </extraargs>

                            </wsdlOption>

 

 

 

JAXB 输入/输出消息类

 

ProcessOrder, ProcessOrderResponseOrder这三个类代表Web Service操作类。这几个类有着各种JAXB注解。ProcessOrder ProcessOrderResponse用来表示RequestResponseRequest拥有出入参数引用,而Response着拥有输出参数引用。

 

为了理解RequestResponse的概念,来看看Web Service将会提交什么样的SOAP Request消息。

 

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

<soap:Body>

      <ns2:processOrder xmlns: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映射为Web Service中的方法processOrder。子元素arg0代表着SOAP payload,映射为输入参数OrderCXF会自动将arg0转换为Order对象,并执行processOrder方法。

 

 

 

服务接口

 

OrderProcessSEI,定义了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 理解CXF FrontendsCode-First》一文执行过程类似。

 

cd contractfirst

#启动server,显示Server ready...消息

mvn test –Pserver

#执行client,显示The order ID 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

你可能感兴趣的:(apache,maven,CXF)