鲁春利的工作笔记,好记性不如烂笔头



WebService只是向客户端暴露WSDL,客户端需要将WSDL转换为相应编程语言书写的代码。JAX-WS的各种实现都提供相应的工具进行WSDL与JAVA之间的相互转换,在CXF的bin目录下提供了多种转换的支持。

E:\mvtech\apache-cxf-3.1.4\bin>ls -l|grep bat
-rwxrwxrwx   1 user     group        1815 Oct 31 04:06 idl2wsdl.bat
-rwxrwxrwx   1 user     group        1815 Oct 31 04:06 java2js.bat
-rwxrwxrwx   1 user     group        1819 Oct 31 04:06 java2ws.bat
-rwxrwxrwx   1 user     group        1789 Oct 31 04:06 mc.bat
-rwxrwxrwx   1 user     group        1836 Oct 31 04:06 wadl2java.bat
-rwxrwxrwx   1 user     group        1826 Oct 31 04:06 wsdl2corba.bat
-rwxrwxrwx   1 user     group        1836 Oct 31 04:06 wsdl2java.bat
-rwxrwxrwx   1 user     group        1786 Oct 31 04:06 wsdl2js.bat
-rwxrwxrwx   1 user     group        1987 Oct 31 04:06 wsdl2service.bat
-rwxrwxrwx   1 user     group        1823 Oct 31 04:06 wsdl2soap.bat
-rwxrwxrwx   1 user     group        1823 Oct 31 04:06 wsdl2xml.bat
-rwxrwxrwx   1 user     group        1821 Oct 31 04:06 wsdlvalidator.bat
-rwxrwxrwx   1 user     group        1821 Oct 31 04:06 xsd2wsdl.bat

# 通过-h参数可以查看帮助
E:\mvtech\apache-cxf-3.1.4\bin>wsdl2java.bat -h

其中wsdl2java.bat可以通过使用URL?wsdl,将WSDL转换为Java类。

常用参数为:

-encoding utf-8          指定生成的文件编码格式
-d  path                 指定生成的java文件存储路径
-p  com.lucl....         指定生成的java文件包名
wsdlurl                  指定WSDL的文件路径,如

-client 生成客户端测试web service的代码;
-server 生成服务器启动web  service的代码;
-impl 生成web service的实现代码;
-ant  生成build.xml文件;
-all 生成所有开始端点代码; 

示例:
E:\mvtech\apache-cxf-3.1.4\bin>wsdl2java.bat -d F:\\ftpfile\\src -p package -V wsdlurl
Loading FrontEnd jaxws ...
Loading DataBinding jaxb ...
wsdl2java -d F:\\ftpfile\\src -p 包全限定名 -V http://localhost:9000/helloWorld?wsdl
wsdl2java - Apache CXF 3.1.4

E:\mvtech\apache-cxf-3.1.4\bin>
# 或者通过jdk自带的wsimport命令
wsimport -d F:/ftpfile/src -p com.lucl.apps.web.webservice.cxf.client
file:/F:/ftpfile/src/GBAService.wsdl


将生成的java类拷贝到eclipse中

wKioL1ZxOHHw5M64AAEdwgosx8I527.jpg

HelloWorld.java              class,对应WebService标注serviceNmae属性指定的HelloWorldImpl,继承自Service
HelloWorldPortType.java      interface,对应WebService标注name属性指定的HelloWorld
ObjectFactory.java           JAXB需要的文件
package-info.java            JAXB需要的文件
SayHi.java                   对应接口方法sayHi
SayHiResponse.java           接口方法sayHi响应数据的封装

1、package-info.java

@javax.xml.bind.annotation.XmlSchema(namespace = "http://server.cxf.webservice.web.apps.lucl.com/")
package com.lucl.apps.web.webservice.cxf.client;

看junit的包的时候发现每个包也都有这么一个java文件,具体用途留待后续分析。

wKioL1ZyTseiDikJAAIfLimXbiY527.jpg


2、ObjectFactory.java

提供了获取类实例的工程方法。

package com.lucl.apps.web.webservice.cxf.client;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    // QName 表示 XML 规范中定义的限定名称
    private final static QName _SayHi_QNAME = new QName("http://server.cxf.webservice.web.apps.lucl.com/", "sayHi");
    private final static QName _SayHiResponse_QNAME = new QName("http://server.cxf.webservice.web.apps.lucl.com/", "sayHiResponse");

    public ObjectFactory() {
        // ......
    }

    /**
     * Create an instance of {@link SayHi }
     * 对应的实际是sayHi方法
     */
    public SayHi createSayHi() {
        return new SayHi();
    }

    /**
     * Create an instance of {@link SayHiResponse }
     * 对应的实际为sayHiResponse方法
     */
    public SayHiResponse createSayHiResponse() {
        return new SayHiResponse();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link SayHi }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://server.cxf.webservice.web.apps.lucl.com/", name = "sayHi")
    public JAXBElement<SayHi> createSayHi(SayHi value) {
        return new JAXBElement<SayHi>(_SayHi_QNAME, SayHi.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link SayHiResponse }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "http://server.cxf.webservice.web.apps.lucl.com/", name = "sayHiResponse")
    public JAXBElement<SayHiResponse> createSayHiResponse(SayHiResponse value) {
        return new JAXBElement<SayHiResponse>(_SayHiResponse_QNAME, SayHiResponse.class, null, value);
    }

}

wKioL1ZyVDKDI91KAAFtu3K_mU0146.jpg

3、HelloWorld.java

实际上对应的是WebService的serviceName标记的类(HelloWorldImpl)。

package com.lucl.apps.web.webservice.cxf.client;

import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.Service;

/**
 * This class was generated by Apache CXF 3.1.4
 * 2015-12-16T18:03:45.079+08:00
 * Generated source version: 3.1.4
 * 
 */
@WebServiceClient(name = "HelloWorld", 
                  wsdlLocation = "http://localhost:9000/helloWorld?wsdl",
                  targetNamespace = "http://server.cxf.webservice.web.apps.lucl.com/") 
public class HelloWorld extends Service {

    public final static URL WSDL_LOCATION;

    public final static QName SERVICE = new QName("http://server.cxf.webservice.web.apps.lucl.com/", "HelloWorld");
    public final static QName HelloWorldPort = new QName("http://server.cxf.webservice.web.apps.lucl.com/", "HelloWorldPort");
    static {
        URL url = null;
        try {
            url = new URL("http://localhost:9000/helloWorld?wsdl");
        } catch (MalformedURLException e) {
            java.util.logging.Logger.getLogger(HelloWorld.class.getName())
                .log(java.util.logging.Level.INFO, 
                     "Can not initialize the default wsdl from {0}", "http://localhost:9000/helloWorld?wsdl");
        }
        WSDL_LOCATION = url;
    }

    public HelloWorld(URL wsdlLocation) {
        super(wsdlLocation, SERVICE);
    }

    public HelloWorld(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public HelloWorld() {
        super(WSDL_LOCATION, SERVICE);
    }
    
    public HelloWorld(WebServiceFeature ... features) {
        super(WSDL_LOCATION, SERVICE, features);
    }

    public HelloWorld(URL wsdlLocation, WebServiceFeature ... features) {
        super(wsdlLocation, SERVICE, features);
    }

    public HelloWorld(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {
        super(wsdlLocation, serviceName, features);
    }    

    /**
     *
     * @return
     *     returns HelloWorldPortType
     */
    @WebEndpoint(name = "HelloWorldPort")
    public HelloWorldPortType getHelloWorldPort() {
        return super.getPort(HelloWorldPort, HelloWorldPortType.class);
    }

    /**
     * 
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns HelloWorldPortType
     */
    @WebEndpoint(name = "HelloWorldPort")
    public HelloWorldPortType getHelloWorldPort(WebServiceFeature... features) {
        return super.getPort(HelloWorldPort, HelloWorldPortType.class, features);
    }

}

4、HelloWorldPortType.java

对应的是Server端的接口HelloWorld。

package com.lucl.apps.web.webservice.cxf.client;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

/**
 * This class was generated by Apache CXF 3.1.4
 * 2015-12-16T18:03:44.816+08:00
 * Generated source version: 3.1.4
 * 
 */
@WebService(targetNamespace = "http://server.cxf.webservice.web.apps.lucl.com/", name = "HelloWorldPortType")
@XmlSeeAlso({ObjectFactory.class})
public interface HelloWorldPortType {

    @WebResult(name = "return", targetNamespace = "")
    @RequestWrapper(localName = "sayHi", targetNamespace = "http://server.cxf.webservice.web.apps.lucl.com/", className = "com.lucl.apps.web.webservice.cxf.client.SayHi")
    @WebMethod
    @ResponseWrapper(localName = "sayHiResponse", targetNamespace = "http://server.cxf.webservice.web.apps.lucl.com/", className = "com.lucl.apps.web.webservice.cxf.client.SayHiResponse")
    public java.lang.String sayHi(
        @WebParam(name = "arg0", targetNamespace = "")
        java.lang.String arg0
    );
}

5、sayHi.java

对应server端HelloWorld接口的方法sayHi。

package com.lucl.apps.web.webservice.cxf.client;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sayHi", propOrder = {
    "arg0"
})
public class SayHi {

    protected String arg0;

    /**
     * 获取arg0属性的值。
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getArg0() {
        return arg0;
    }

    /**
     * 设置arg0属性的值。
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setArg0(String value) {
        this.arg0 = value;
    }

}

6、sayHiResponse.java

工具根据wsdl生成的HelloWorld接口的sayHi方法的响应。

package com.lucl.apps.web.webservice.cxf.client;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sayHiResponse", propOrder = {
    "_return"
})
public class SayHiResponse {

    @XmlElement(name = "return")
    protected String _return;

    /**
     * 获取return属性的值。
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getReturn() {
        return _return;
    }

    /**
     * 设置return属性的值。
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setReturn(String value) {
        this._return = value;
    }

}

注意:如果server端的HelloWorld接口中sayHi方法有异常被throw出来,那么在通过wsdl2java工具生成java代码时,会生成异常对应的JavaBean和实现了Exception的java类。