WebService的wsdl详解

webservice服务的wsdl内容详解,以及如何根据其内容编写调用代码

wsdl示例

展示一个webservice的wsdl,及调用这个接口的Axis客户端

wsdl

This XML file does not appear to have any style information associated with it. The document tree is shown below.
                                                                                                                                                   

Axis客户端

用于调用上面的webservice服务

org.apache.axisaxis1.4
import client.WSContext;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.w3c.dom.Document;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.rpc.ServiceException;
import javax.xml.soap.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
public static void other(){ QName returnType = new javax.xml.namespace.QName("urn:client", "WSContext");
        Object result = null;
        try { // 创建一个新的Service对象
            Service service = new Service();
            Call call = (Call) service.createCall();
            // 设置目标webservice地址,注意去掉 问号与wsdl
            call.setTargetEndpointAddress(new URL("http://10.10.1.190:6889/ormrpc/services/EASLogin"));
            //设置方法名
            call.setOperationName(new QName( "login"));
            // 设置传入参数的xml及类型,可以不写
            //call.addParameter("userName", XMLType.XSD_STRING, ParameterMode.IN);
            //call.addParameter("password", XMLType.XSD_STRING, ParameterMode.IN);
            //call.addParameter("slnName", XMLType.XSD_STRING, ParameterMode.IN);
            //call.addParameter("dcName", XMLType.XSD_STRING, ParameterMode.IN);
            //call.addParameter("language", XMLType.XSD_STRING, ParameterMode.IN);
            //call.addParameter("dbType", XMLType.XSD_INT, ParameterMode.IN);
            // 设置返回参数的xml及类型,设置请求参数时要写参数名,而返回值不用
            call.setReturnType(returnType);
            call.setReturnClass(WSContext.class);
            //设置返回值名字,可以不写
            //call.setReturnQName(new QName("", "loginReturn"));
            //设置axis的序列化,否则无法接受自定义类型WSContext
            Class sf = org.apache.axis.encoding.ser.BeanSerializerFactory.class;
            Class df = org.apache.axis.encoding.ser.BeanDeserializerFactory.class;
            call.registerTypeMapping(WSContext.class, returnType, sf, df, false);
            // 构造请求的参数
            String userName = "xdgt";
            String password = "123456";
            String slnName = "eas";
            String dcName = "gg01";
            String language = "L2";
            Integer dbType = 2;
            // 调用WebService方法
            WSContext ws = (WSContext) call.invoke(new Object[] {userName, password, slnName, dcName, language, dbType});
            // 处理返回的结果
            System.out.println("Response: " + ws.getSessionId());
        } catch (Exception e) { result = "{\"status\": \"error\",\"msg\":\"" + e.getMessage() + "\"}";
        }
        System.out.println(result);
}

返回类型WSContext代码,这个建议用axis命令生成,因为内部涉及wsdl的拼接,比较麻烦,而且实际开发中,有可能你并不了解对方的代码结构

axis命令生成参考:

https://blog.csdn.net/onePlus5T/article/details/139122866
/**
 * WSContext.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */
package client;
public class WSContext  implements java.io.Serializable { private int dbType;
    private String dcName;
    private String password;
    private String sessionId;
    private String slnName;
    private String userName;
    public WSContext() { }
    public WSContext(
            int dbType,
            String dcName,
            String password,
            String sessionId,
            String slnName,
            String userName) { this.dbType = dbType;
        this.dcName = dcName;
        this.password = password;
        this.sessionId = sessionId;
        this.slnName = slnName;
        this.userName = userName;
    }
    /**
     * Gets the dbType value for this WSContext.
     *
     * @return dbType
     */
    public int getDbType() { return dbType;
    }
    /**
     * Sets the dbType value for this WSContext.
     *
     * @param dbType
     */
    public void setDbType(int dbType) { this.dbType = dbType;
    }
    /**
     * Gets the dcName value for this WSContext.
     *
     * @return dcName
     */
    public String getDcName() { return dcName;
    }
    /**
     * Sets the dcName value for this WSContext.
     *
     * @param dcName
     */
    public void setDcName(String dcName) { this.dcName = dcName;
    }
    /**
     * Gets the password value for this WSContext.
     *
     * @return password
     */
    public String getPassword() { return password;
    }
    /**
     * Sets the password value for this WSContext.
     *
     * @param password
     */
    public void setPassword(String password) { this.password = password;
    }
    /**
     * Gets the sessionId value for this WSContext.
     *
     * @return sessionId
     */
    public String getSessionId() { return sessionId;
    }
    /**
     * Sets the sessionId value for this WSContext.
     *
     * @param sessionId
     */
    public void setSessionId(String sessionId) { this.sessionId = sessionId;
    }
    /**
     * Gets the slnName value for this WSContext.
     *
     * @return slnName
     */
    public String getSlnName() { return slnName;
    }
    /**
     * Sets the slnName value for this WSContext.
     *
     * @param slnName
     */
    public void setSlnName(String slnName) { this.slnName = slnName;
    }
    /**
     * Gets the userName value for this WSContext.
     *
     * @return userName
     */
    public String getUserName() { return userName;
    }
    /**
     * Sets the userName value for this WSContext.
     *
     * @param userName
     */
    public void setUserName(String userName) { this.userName = userName;
    }
    private Object __equalsCalc = null;
    public synchronized boolean equals(Object obj) { if (!(obj instanceof WSContext)) return false;
        WSContext other = (WSContext) obj;
        if (obj == null) return false;
        if (this == obj) return true;
        if (__equalsCalc != null) { return (__equalsCalc == obj);
        }
        __equalsCalc = obj;
        boolean _equals;
        _equals = true &&
                this.dbType == other.getDbType() &&
                ((this.dcName==null && other.getDcName()==null) ||
                        (this.dcName!=null &&
                                this.dcName.equals(other.getDcName()))) &&
                ((this.password==null && other.getPassword()==null) ||
                        (this.password!=null &&
                                this.password.equals(other.getPassword()))) &&
                ((this.sessionId==null && other.getSessionId()==null) ||
                        (this.sessionId!=null &&
                                this.sessionId.equals(other.getSessionId()))) &&
                ((this.slnName==null && other.getSlnName()==null) ||
                        (this.slnName!=null &&
                                this.slnName.equals(other.getSlnName()))) &&
                ((this.userName==null && other.getUserName()==null) ||
                        (this.userName!=null &&
                                this.userName.equals(other.getUserName())));
        __equalsCalc = null;
        return _equals;
    }
    private boolean __hashCodeCalc = false;
    public synchronized int hashCode() { if (__hashCodeCalc) { return 0;
        }
        __hashCodeCalc = true;
        int _hashCode = 1;
        _hashCode += getDbType();
        if (getDcName() != null) { _hashCode += getDcName().hashCode();
        }
        if (getPassword() != null) { _hashCode += getPassword().hashCode();
        }
        if (getSessionId() != null) { _hashCode += getSessionId().hashCode();
        }
        if (getSlnName() != null) { _hashCode += getSlnName().hashCode();
        }
        if (getUserName() != null) { _hashCode += getUserName().hashCode();
        }
        __hashCodeCalc = false;
        return _hashCode;
    }
    // Type metadata
    private static org.apache.axis.description.TypeDesc typeDesc =
            new org.apache.axis.description.TypeDesc(WSContext.class, true);
    static { typeDesc.setXmlType(new javax.xml.namespace.QName("urn:client", "WSContext"));
        org.apache.axis.description.ElementDesc elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("dbType");
        elemField.setXmlName(new javax.xml.namespace.QName("", "dbType"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"));
        elemField.setNillable(false);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("dcName");
        elemField.setXmlName(new javax.xml.namespace.QName("", "dcName"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("password");
        elemField.setXmlName(new javax.xml.namespace.QName("", "password"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("sessionId");
        elemField.setXmlName(new javax.xml.namespace.QName("", "sessionId"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("slnName");
        elemField.setXmlName(new javax.xml.namespace.QName("", "slnName"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("userName");
        elemField.setXmlName(new javax.xml.namespace.QName("", "userName"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
    }
}

wsdl标签大意

♦ types元素

使用XML模式语言,声明在WSDL文档中的其他位置使用的复杂数据类型与元素,可理解为就是**定义webservice方法请求与响应参数的**

♦ import元素

类似于XML模式文档中的import元素,用于从其他WSDL文档中导入WSDL定义;

♦ message元素

使用在WSDL文档的type元素中定义或在import元素引用的外部WSDL文档中定义的XML模式的内置类型、复杂类型或元素描述了消息的有效负载;

♦ portType元素 和 operation元素

描述了Web服务的接口并定义了他的方法。portType元素和operation元素类似于java接口和接口中定义的方法声明。operation元素使用一个或者多个message类型来定义他的输入和输出的有效负载;

♦ Binding元素

将portType元素和operation元素赋给一个特殊的协议和编码样式;

♦ service元素

负责将Internet地址赋给一个具体的绑定;


具体解释

wsdl:definitions标签

xmlns:xxxx

做此wsdl的定义,里面有很多 xmlns:xxxx,其中后半部分的xxxx会在其他标签中被引用

比如,在上面wsdl文件中的 wsdl:message的Response标签 中,返回类型定义为:type=“tns1:WSContext”,则对应Axis客户端代码就要这样写:

//因为tns1在 标签 中定义值为 urn:client,所以要向下面这样拼
call.setReturnType(new javax.xml.namespace.QName("urn:client", "WSContext"));
//一般如果不是java中自带的类型,比如string、int等,大概率都是自定义类型,
//此处的WSContext肯定是自定义类型,所以必须在这里赋值class类型,因为Axis不知道WSContext是什么类型
call.setReturnClass(WSContext.class);

假如是 type=“xsd:string”,则对应Axis客户端代码就是:

//xsd属于xml自带标签,进入org.apache.axis.Constants.XSD_STRING的源码可以看见其值就是xsd:string
call.setReturnType(org.apache.axis.Constants.XSD_STRING);

targetNamespace

webserivce的名称空间,一般与方法名拼接一起使用,axis代码使用如下:

call.setOperationName(new QName("名称空间", "方法名"));

注意:targetNamespace不是必须与方法名拼接在一起进行axis客户端调用,要看 wsdl:message 标签的方法中是否有前缀

比如下面:方法Response 与 Request 中都有前缀ns0,而ns0的值恰好与targetNamespace一致,所以上面的:

new QName("名称空间", "方法名")

就没问题了

但是本wsdl示例文档的 wsdl:message 标签方法无前缀,比如下图的logout方法:

则axis代码就可以直接写一个方法名:

call.setOperationName(new QName( "logout"));

wsdl:message标签

详解

方法标签,对应发布webservice的接口方法,其中

  • xxxResponse代表接口方法的返回
  • xxxRequest或者直接xxx方法名代表接口方法的接收

比如本文的wsdl示例文档中的:

正对应其5个方法:

而wsdl:message标签的内容,正对应请求参数与返回值参数

  • 请求参数对应上图request中的5个
  • 返回参数对应上图的tns1:WSContext,也就是下面wsdl:types标签中的类型定义,是5个小类型的合体

    axis调用

    1.这里对应本文wsdl示例的axis代码调用如下,因为对应方法名的loginRequest、loginResponse没有前缀修饰:

    call.setOperationName(new QName( "login"));
    

    2.但如果是下面这种,就必须有前缀对应的QName拼接:

    call.setOperationName(new QName("tns在内定义的值","方法名emeService"));
    

    wsdl:definitions中的tns展示,大部分tns与名称空间targetNamespace相同

    wsdl:types标签

    详解1

    声明在其他标签中要使用的元素和类型,比如接口方法参数类型、返回值类型

    比如本文档示例的wsdl中,wsdl:types标签内容如下,其实就是定义了接口方法的参数类型:

                 

    其中,complexType为一个复合类型,它包含的具体小类型在sequence标签的element中,当我们调用

    的方法时,返回的结果格式如下,其实就是返回了WSContext类,这个类包含了其他5个字符串和整数的属性

    axis调用1

    结合最上面wsdl示例的message:

    请求:

          

    响应:

     

    此wsdl:types标签对应的调用代码如下

    注意:请求参数需要写参数名,设置返回值时不用写返回值名

    请求:

    call.addParameter("userName", XMLType.XSD_STRING, ParameterMode.IN);
    call.addParameter("password", XMLType.XSD_STRING, ParameterMode.IN);
    call.addParameter("slnName", XMLType.XSD_STRING, ParameterMode.IN);
    call.addParameter("dcName", XMLType.XSD_STRING, ParameterMode.IN);
    call.addParameter("language", XMLType.XSD_STRING, ParameterMode.IN);
    call.addParameter("dbType", XMLType.XSD_INT, ParameterMode.IN);
    

    响应:

    //设置wsdl中返回值类型及其修饰标签
    call.setReturnType(new QName("urn:client", "WSContext"));
    //因为返回值类型为WSContext,不是基本类型,所以必须设置其calss类,否则报错
    call.setReturnClass(WSContext.class);
    

    这个响应的返回值类型,推荐由Axis的命令直接生成,内部构成比较复杂

    详解2

    在举一个不同格式的例子

    下面这种格式的wsdl:types标签,与上面大同小异,意思就是:

    在wsdl:types中,定义了**emeService方法 ** 的

    • 请求参数类型是String,名称是arg0
    • 返回值类型是String,名称是return

      结果证明:

      axis调用2

      上面的返回值名字为return,类型为xs:string

      注意:axis设置请求参数时需要写参数名,而设置返回值时不用写返回值名

      xs:string在axis中可以用代码XMLType.XSD_STRING标识,java基本类型都可以用XMLType表示

      call.setReturnType(XMLType.XSD_STRING);
      

      wsdl:portType标签

      表达了发布webservice接口的代码结构

      以本文wsdl文档示例为例:

      • wsdl:portType的name的值:一般对应发布webservice的接口名。
      • wsdl:operation的name的值:对应webservice接口的方法名,parameterOrder为方法参数名。
      • wsdl:input与wsdl:output:对应了输入输出,即接口方法请求与返回的message定义,可以根据其name名字去wsdl:message标签找对应的方法定义。

        wsdl:binding与wsdl:service标签

        好像不涉及Axis代码调用需要编写的部分,暂时没有仔细分析

        • Binding - 特定端口类型的具体协议和数据格式规范的绑定。
        • Port - 定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点。
        • Service- 相关服务访问点的集合。