WebService对象可空的困惑,关于nillable和minOccurs soap java .net wsdl的区别

 

WebService对象可空的困惑,关于nillable和minOccurs

  7220人阅读  评论(2)  收藏  举报
  分类:
 
 

术语约定
文章中会反复出现[值类型]、[包装类型]、[普通引用类型]、[元素节点]和[元素取值]的表述
1> [值类型]指的是java和.NET中的基本数据类型,如:int;
2> [包装类型]指的是java中的包装类和.NET中的Nullable<T>类型,如:Integer、int?;
3> [普通引用类型]指的是除包装类型外的其它引用类型;
4> [元素节点]指的是xml文档中的一个标签节点,我们可以说[元素节点]是必输还是非必输,如:<Name>lubiao</Name>;
5> [元素取值]指的是xml标签节点的内容,我们可以说[元素取值]是空还是非空,如:<Name>lubiao</Name>表示元素取值不为空,<Name xsi:nil="true"/>表示元素取值为空;

1、首先来看minOccurs和Nillable的定义
minOccurs
:表示XML文档中某个[元素节点] 是否可以不出现,默认值为1,表示必须出现
nillable:表示XML文档中某个[元素取值] 是否可以为空(形如:<name xsi:nil="true" />),默认值为false,表示不能为空
那么,minOccurs和nillable的组合形式就会有4种,如下:
例一,值类型:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <element name="id1" type="int" minOccurs="0" nillable="true"/>  
  2. <element name="id2" type="int" minOccurs="0" nillable="false"/>  
  3. <element name="id3" type="int" minOccurs="1" nillable="true"/>  
  4. <element name="id4" type="int" minOccurs="1" nillable="false"/>  

例二,引用类型:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <element name="name1" type="string" minOccurs="0" nillable="true"/>  
  2. <element name="name2" type="string" minOccurs="0" nillable="false"/>  
  3. <element name="name3" type="string" minOccurs="1" nillable="true"/>  
  4. <element name="name4" type="string" minOccurs="1" nillable="false"/>  

2、Java和.NET自动生成WSDL的规则
在实际开发时我们通常的做法是先编写Server端代码,然后利用工具自动生成wsdl描述,最后再利用工具读取wsdl进而生成客户端程序。那么用工具生成wsdl和用工具反向生成代理程序的规则是什么呢?下来对此进行实例分析:
2.1 先看.NET生成wsdl的规则
实验时所用的开发工具为VS 2010,用vs开发WebService的资料,百度搜索一大推,这里不赘述。
2.1.1、定义数据实体:Person.cs

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Person   
  2. {  
  3.     public int Id { getset; } //值类型  
  4.     public string Name { getset; }//普通引用类型  
  5.     public int? PhoneNbr { getset; }//包装类型  
  6. }  

2.1.2、定义服务类:WebService.cs

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /// <summary>  
  2. ///WebService 的摘要说明  
  3. /// </summary>  
  4. [WebService(Namespace = "http://tempuri.org/")]  
  5. [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]  
  6. public class WebService : System.Web.Services.WebService {  
  7.   
  8.     public WebService () {  
  9.        //如果使用设计的组件,请取消注释以下行   
  10.         //InitializeComponent();   
  11.     }  
  12.   
  13.     [WebMethod]  
  14.     public string HelloWorld(int id,int? phoneNbr,string name,Person person) {  
  15.         return "Hello World";  
  16.     }  
  17.       
  18. }  

helloWorld方法有4个参数,前三个参数和Person类的三个属性是一样的,加入这三个参数的目的是进行对比测试。
2.1.3、查看生成的wsdl

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <wsdl:definitions xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">  
  3.   <wsdl:types>  
  4.     <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">  
  5.       <s:element name="HelloWorld">  
  6.         <s:complexType>  
  7.           <s:sequence>  
  8.             <s:element minOccurs="1" maxOccurs="1" name="id" type="s:int" />  
  9.             <!--nillable默认为false,minOccurs等于1:即id元素为必输,且值不能为空-->  
  10.             <s:element minOccurs="1" maxOccurs="1" name="phoneNbr" nillable="true" type="s:int" />  
  11.             <!--nillable等于true,minOccurs等于1:即phoneNbr元素为必输,但值可以为空-->  
  12.             <s:element minOccurs="0" maxOccurs="1" name="name" type="s:string" />  
  13.             <!--nillable默认为false,minOccurs等于0:即name元素为非必输,但值不能为空-->  
  14.             <s:element minOccurs="0" maxOccurs="1" name="person" type="tns:Person" />  
  15.             <!--nillable默认为false,minOccurs等于0:即person元素为非必输,但值不能为空-->  
  16.           </s:sequence>  
  17.         </s:complexType>  
  18.       </s:element>  
  19.       <s:complexType name="Person">  
  20.         <s:sequence>  
  21.           <s:element minOccurs="1" maxOccurs="1" name="Id" type="s:int" />  
  22.           <!--nillable默认为false,minOccurs默认为1:即id元素为必输,且值不能为空-->  
  23.           <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" />  
  24.           <!--nillable默认为false,minOccurs等于0:即Name元素为非必输,但值不能为空-->  
  25.           <s:element minOccurs="1" maxOccurs="1" name="PhoneNbr" nillable="true" type="s:int" />  
  26.           <!--nillable默认为false,minOccurs等于1:即PhoneNbr元素为必输,但值可以为空-->  
  27.         </s:sequence>  
  28.       </s:complexType>  
  29.       <s:element name="HelloWorldResponse">  
  30.         <s:complexType>  
  31.           <s:sequence>  
  32.             <s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />  
  33.           </s:sequence>  
  34.         </s:complexType>  
  35.       </s:element>  
  36.     </s:schema>  
  37.   </wsdl:types>  
  38.  </wsdl:definitions>  

2.1.4、得出结论  
id参数和Person.Id属性都为值类型:[元素节点] 都必输,[元素取值] 都不能为空
* phoneNbr参数和Person.PhoneNbr属性都是包装类型:[元素节点] 都必输,但[元素取值] 都可以为空;
* name参数和Person.Name属性都是普通引用类型:[元素节点] 都可以不输,但[元素取值] 都不能为空;
* person参数是普通引用类型:[元素节点] 可以不输,但[元素取值] 不能为空。
2.2 再看Java的规则
首先,先熟悉在eclipse中快速开发webservice程序的步骤,参考链接:http://www.blogjava.net/parable-myth/archive/2010/08/03/327802.html,此次实验采用的就是这种快速开发方式(注:不同的框架和工具会可能会有不同的生成规则),所用ecllipse版本为:
    Version: Juno Service Release 1
    Build id: 20121004-1855
2.2.1、定义数据实体:Person.java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.lubiao.axis;  
  2.   
  3. public class Person  implements java.io.Serializable {  
  4.     private int id;//编号,值类型  
  5.     private java.lang.String name;//姓名,普通引用类型  
  6.     private Integer phoneNbr;//电话,包装类型  
  7.       
  8.     public int getId() {return id;}  
  9.     public void setId(int id) {this.id = id;}  
  10.       
  11.     public java.lang.String getName() {return name;}  
  12.     public void setName(java.lang.String name) {this.name = name;}  
  13.   
  14.     public Integer getPhoneNbr() {return phoneNbr;}  
  15.     public void setPhoneNbr(Integer phoneNbr) {this.phoneNbr = phoneNbr;}  
  16. }  

2.2.2、定义服务类:WebServiceTest.java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.lubiao.axis;  
  2.   
  3. public class WebServiceTest{  
  4.     public String helloWorld(int id,Integer phoneNbr,String name,Person person){  
  5.         return "Hello World";  
  6.     }  
  7. }  

helloWorld方法有4个参数,前三个参数和Person类的三个属性是一样的,加入这三个参数的目的是进行对比测试。
2.2.3、查看生成的Wsdl

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <wsdl:definitions targetNamespace="http://axis.lubiao.com" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://axis.lubiao.com" xmlns:intf="http://axis.lubiao.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
  3.   <!--WSDL created by Apache Axis version: 1.4 Built on Apr 22, 2006 (06:55:48 PDT)-->  
  4.   <wsdl:types>  
  5.     <schema elementFormDefault="qualified" targetNamespace="http://axis.lubiao.com" xmlns="http://www.w3.org/2001/XMLSchema">  
  6.       <element name="helloWorld">  
  7.         <complexType>  
  8.           <sequence>  
  9.             <element name="id" type="xsd:int"/>  
  10.             <!--nillable默认为false,minOccurs默认为1:即id元素为必输,且值不能为空-->  
  11.             <element name="phoneNbr" type="xsd:int"/>  
  12.             <!--nillable默认为false,minOccurs默认为1:即phoneNbr元素为必输,且值不能为空-->  
  13.             <element name="name" type="xsd:string"/>  
  14.             <!--nillable默认为false,minOccurs默认为1:即name元素为必输,且值不能为空-->  
  15.             <element name="person" type="impl:Person"/>  
  16.             <!--nillable默认为false,minOccurs默认为1:即person元素为必输,且值不能为空-->  
  17.           </sequence>  
  18.         </complexType>  
  19.       </element>  
  20.       <complexType name="Person">  
  21.         <sequence>  
  22.           <element name="id" type="xsd:int"/>  
  23.           <!--nillable默认为false,minOccurs默认为1:即id元素为必输,且值不能为空-->  
  24.           <element name="name" nillable="true" type="xsd:string"/>  
  25.           <!--nillable默认为true,minOccurs默认为1:即name元素为必输,但值可以为空-->  
  26.           <element name="phoneNbr" nillable="true" type="xsd:int"/>  
  27.           <!--nillable默认为true,minOccurs默认为1:即phoneNbr元素为必输,但值可以为空-->  
  28.         </sequence>  
  29.       </complexType>  
  30.       <element name="helloWorldResponse">  
  31.         <complexType>  
  32.           <sequence>  
  33.             <element name="helloWorldReturn" type="xsd:string"/>  
  34.           </sequence>  
  35.         </complexType>  
  36.       </element>  
  37.     </schema>  
  38.   </wsdl:types>  
  39.   <!-- 其它元素省略 -->  
  40. </wsdl:definitions>  

2.2.4、得出结论
* id参数和Person.id属性都是值类型:[元素节点] 都必输,[元素取值] 都不能为空;
* phoneNbr参数和Person.phoneNbr属性都是包装类型:[元素节点] 都必输,但前者[元素取值]不能为空,后者[元素取值]可以为空;
* name参数和Person.name属性都是普通的引用类型:[元素节点] 都必输,但前者[元素取值]不能为空,后者[元素取值]可以为空;
* person参数属于普通引用类型:[元素节点]必输,且[元素取值]不能为空;
*总结:此框架生成wsdl时认为:
        1、作为方法参数时,不管是值类型、包装类型还是普通引用类型,[元素节点]都为必输项,且[元素取值]都不能为空;
        2、作为对象属性时,不管是值类型、包装类型还是普通引用类型,[元素节点]都为必输项,其中值类型的[元素取值]不能为空,但包装类型和普通引用类型的[元素取值]可以为空。

2.3、Java和.NET的异同
其一,对于值类型:

            Java和.NET都认为值类型不论是作为 [方法参数时] 还是 [对象属性时] ,[元素节点]都为必输项,且[元素取值]都不能为空。
             (都合理:这符合值类型的特点,总有一个值)
其二,对于包装类型:
            作为方法参数时:java和.NET都认为[元素节点]是必输的,但java认为[元素取值]不能为空,而.NET认为[元素取值]可以为空;
               (.NET合理,Java不合理。java既要求必输又要求值不能为空,那空对象怎么传入?可以通过生成客户端代理进行验证(这里不再演示),对于phoneNbr参数客户端代码变成了int类型,而服务端可是Integer类型)
            作为对象属性时:java和.NET都认为[元素是节点]必输的,而[元素取值]是可以为空的;
                (都合理。java和.net都要求节点必须出现,然后以nillable=true标识可以传入空值)
其三,对于普通引用类型:
            作为方法参数时:java和.NET都认为[元素取值]是不能为空的,但Java同时认为[元素节点]是必输的,而.NET认为[元素节点]是非必输的;
                (.NET合理,Java不合理。java既要求节点必输还要求值不能为空,那空对象怎么传入?)
            
作为对象属性时:java认为[元素节点]是必输的、[元素取值]是可空的;.NET认为[元素节点]是非必输的、[元素取值]是不可空的。
                (都合理。java始终要求必输,但以nillable=true标识可以传入空对象;.NET始终要求元素取值不能为空,但以minOccurs=0来标识可以传入空对象)
总结:
作为参数时,java出现了很多不合理的情况,可能是因为选的这个框架有bug,这里不再关心,主要看作为对象属性时的情况。文章最开始的时候说到minOccurs和nillable会有4种组合方式,在上面的实验中java用到了两种,而.NET用到了3种,分别为:
Java:[ minOccurs=1,nillable=false ] 和 [ minOccurs=1,nillable=true ],前者对应值类型,后者对应引用类型(包装类型和普通引用类型),java压根没用minOccrs=0
.NET:[ minOccurs=1,nillable=false ]、[ minOccurs=1,nillable=true ] 和[ minOccurs=0,nillable=false],前者对应值类型,再者对应包装类型,最后对应普通引用类型。
3、Java和.NET由WSDL自动生成代码的规则
接着上面的实验结果,先来做最简单的测试:1、用java的client对接java的service生成代码;2、用.NET的client对接.NET的Service生成代码,然后分别观察Client端自动生成的Person类和Server段的Person是否完全一致。这里不再演示,只说结论,结论是:生成的Person分别和各自Server端的完全相同。
那如果用[ java对接.NET ] 或者[ 用.NET对接java ],会是什么结果呢?等一等,这么问好像有问题,哪有什么谁对接谁,大家对接的都是wsdl,哪里知道wsdl后面是什么平台!!嗯,那就把minOccurs和nillable的四种组合都列出来,看java和.NET的生成规则分别是什么样的,继续。
3.1 先看.NET的规则
3.1.1 定义WSDL,限于篇幅只列出类型定义部分

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <schema xmlns="<a target="_blank" href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>xmlns:sys="<a target="_blank" href="http://com.lubiao.service/system">http://com.lubiao.service/system</a>targetNamespace="<a target="_blank" href="http://com.lubiao.service/system">http://com.lubiao.service/system</a>elementFormDefault="qualified">  
  3.   <complexType name="Person">  
  4.     <sequence>  
  5.       <element name="id1" type="long" minOccurs="0" nillable="true"/>  
  6.       <element name="id2" type="long" minOccurs="0" nillable="false"/>  
  7.       <element name="id3" type="long" minOccurs="1" nillable="true"/>  
  8.       <element name="id4" type="long" minOccurs="1" nillable="false"/>  
  9.       <element name="name1" type="string" minOccurs="0" nillable="true"/>  
  10.       <element name="name2" type="string" minOccurs="0" nillable="false"/>  
  11.       <element name="name3" type="string" minOccurs="1" nillable="true"/>  
  12.       <element name="name4" type="string" minOccurs="1" nillable="false"/>  
  13.     </sequence>  
  14.   </complexType>  
  15.     
  16.   <complexType name="PersonResponse">  
  17.     <sequence>  
  18.       <element name="id" type="string" minOccurs="0"/>  
  19.     </sequence>  
  20.   </complexType>  
  21.     
  22.   <element name="GetPerson" type="sys:Person"></element>  
  23.   <element name="GetPersonResponse" type="sys:PersonResponse"></element>  
  24. </schema>  

id对应的是值类型,name对应的是引用类型
3.1.2 生成数据类

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml""4.0.30319.18058")]  
  2. [System.SerializableAttribute()]  
  3. [System.Diagnostics.DebuggerStepThroughAttribute()]  
  4. [System.ComponentModel.DesignerCategoryAttribute("code")]  
  5. [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://com.csii.bank.core/system")]  
  6. public partial class Person{  
  7.               
  8.     private System.Nullable<long> id1Field;  
  9.       
  10.     private bool id1FieldSpecified;  
  11.       
  12.     private long id2Field;  
  13.       
  14.     private bool id2FieldSpecified;  
  15.       
  16.     private System.Nullable<long> id3Field;  
  17.       
  18.     private long id4Field;  
  19.       
  20.     private string name1Field;  
  21.       
  22.     private string name2Field;  
  23.       
  24.     private string name3Field;  
  25.       
  26.     private string name4Field;  
  27.               
  28.     /// <remarks/>  
  29.     [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]  
  30.     public System.Nullable<long> id1 {  
  31.         get {  
  32.             return this.id1Field;  
  33.         }  
  34.         set {  
  35.             this.id1Field = value;  
  36.         }  
  37.     }  
  38.       
  39.     /// <remarks/>  
  40.     [System.Xml.Serialization.XmlIgnoreAttribute()]  
  41.     public bool id1Specified {  
  42.         get {  
  43.             return this.id1FieldSpecified;  
  44.         }  
  45.         set {  
  46.             this.id1FieldSpecified = value;  
  47.         }  
  48.     }  
  49.       
  50.     /// <remarks/>  
  51.     public long id2 {  
  52.         get {  
  53.             return this.id2Field;  
  54.         }  
  55.         set {  
  56.             this.id2Field = value;  
  57.         }  
  58.     }  
  59.       
  60.     /// <remarks/>  
  61.     [System.Xml.Serialization.XmlIgnoreAttribute()]  
  62.     public bool id2Specified {  
  63.         get {  
  64.             return this.id2FieldSpecified;  
  65.         }  
  66.         set {  
  67.             this.id2FieldSpecified = value;  
  68.         }  
  69.     }  
  70.       
  71.     /// <remarks/>  
  72.     [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]  
  73.     public System.Nullable<long> id3 {  
  74.         get {  
  75.             return this.id3Field;  
  76.         }  
  77.         set {  
  78.             this.id3Field = value;  
  79.         }  
  80.     }  
  81.       
  82.     /// <remarks/>  
  83.     public long id4 {  
  84.         get {  
  85.             return this.id4Field;  
  86.         }  
  87.         set {  
  88.             this.id4Field = value;  
  89.         }  
  90.     }  
  91.       
  92.     /// <remarks/>  
  93.     [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]  
  94.     public string name1 {  
  95.         get {  
  96.             return this.name1Field;  
  97.         }  
  98.         set {  
  99.             this.name1Field = value;  
  100.         }  
  101.     }  
  102.       
  103.     /// <remarks/>  
  104.     public string name2 {  
  105.         get {  
  106.             return this.name2Field;  
  107.         }  
  108.         set {  
  109.             this.name2Field = value;  
  110.         }  
  111.     }  
  112.       
  113.     /// <remarks/>  
  114.     [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]  
  115.     public string name3 {  
  116.         get {  
  117.             return this.name3Field;  
  118.         }  
  119.         set {  
  120.             this.name3Field = value;  
  121.         }  
  122.     }  
  123.       
  124.     /// <remarks/>  
  125.     public string name4 {  
  126.         get {  
  127.             return this.name4Field;  
  128.         }  
  129.         set {  
  130.             this.name4Field = value;  
  131.         }  
  132.     }  
  133. }  

分析:
id1:可空类型、特性:IsNullable=true、生成了对应的id1Specified
id2:值类型、特性:IsNullable=false、生成了对应的id2Specified
id3:可空类型、特性:IsNullable=true
id4:值类型、特性:IsNullable=false
name1:引用类型、特性:IsNullable=true
name2:引用类型、特性:IsNullable=false
name3:引用类型、特性:IsNullable=true
name4:引用类型、特性:IsNullable=false
3.1.3 查看SOAP报文
将可为null的属性都置位null,然后查看SOAP报文是什么样子的
C#代码1:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Person p=new Person();  
  2. p.id1 = null;  
  3. p.id2 = 123;  
  4. p.id3 = null;  
  5. p.id4 = 456;  
  6. p.name1 = null;  
  7. p.name2 = null;  
  8. p.name3 = null;  
  9. p.name4 = null;  

C#代码2:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Person p=new Person();  
  2. p.id1 = null;  
  3. p.id1Specified = true;  
  4. request.id2 = 123;  
  5. p.id1Specified = true;  
  6. p.id3 = null;  
  7. p.id4 = 456;  
  8. p.name1 = null;  
  9. p.name2 = null;  
  10. p.name3 = null;  
  11. p.name4 = null;  

SOAP报文1:对应C#代码1,只贴出Person部分:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <Person>  
  2.       <id3 xsi:nil="true" />  
  3.       <id4>456</id4>  
  4.       <name1 xsi:nil="true" />  
  5.       <name3 xsi:nil="true" />  
  6. </Person>  

SOAP报文2:对应C#代码2,只贴出Person部分:

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <Person>  
  2.       <id1 xsi:nil="true" />  
  3.       <id2>123</id2>  
  4.       <id3 xsi:nil="true" />  
  5.       <id4>456</id4>  
  6.       <name1 xsi:nil="true" />  
  7.       <name3 xsi:nil="true" />  
  8. </Person>  

3.1.4 得出结论
其一:对于值类型和包装类型

minOccurs="0" 组合nillable="true"时
会生成包装类型(id1),同时会生成对应的id1Specified属性,为什么会生成带Specified的属性呢?这是因为minOccurs="0"的缘故,minOccurs=0意味着元素节点可以不出现,那到底是出现呢?还是不出现呢?工具自己没了主意,所以生成了一个xxxSpecified属性,该属性默认值为false,只有给它指定true的时候[元素节点]才会出现到soap报文中。
minOccurs="0"组合nillable="false"时
会生成值类型(id2),同时会生成对应的id2Specified属性(原因同上)
minOccurs="1" 组合nillable="true"时
会生成包装(id3),不会生成Specified属性(因为元素节点必输)。
minOccurs=“1”组合nillable=“false”时
会生成值类型(id4),不会生成Specified属性(因为元素节点必输)。
其二:对于普通引用类型
name1、name3:
只要nillable=true不管minOccurs等于什么,[null对象]序列化的时候都以[元素取值]为空方式来体现这是一个空对象。
name2、name4:   
只要nillable=false不管minOccurs等于什么,[null对象]序列化时都以[元素节点]不出现的方式来体现这是一个空对象。(上面实验时,Server端对soap报文进行了schema验证,所以name4传null会报错的)

总结:
* .NET在wsdl_2_C# 和C#_2_wsdl时的思路其实是一致的,1、生成值类型还是包装类型先看nillable属性、然后再看minOccurs属性来控制是否生成xxxSpecified属性;2、而生成普通引用类型时只关心nillable属性,nillable=true就采用nil=true的方式发送null对象,nillabe=false则采用[元素节点]不出现的方式发送null对象,压根就不关心minOccurs是神马。
* 前面说到name4=null时,Server端会报错,所以 对于引用类型:minOccurs=1和nillable=false的组合是没有意义的,这种组合无法让空对象传输过来
3.2 再看Java的规则

3.2.1 定义WSDL,限于篇幅只列出类型定义部分
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#000000;"><?xml version="1.0" encoding="UTF-8"?>  
  2. <schema xmlns="<a target="_blank" href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>xmlns:sys="<a target="_blank" href="http://com.lubiao.service/system">http://com.lubiao.service/system</a>targetNamespace="<a target="_blank" href="http://com.lubiao.service/system">http://com.lubiao.service/system</a>elementFormDefault="qualified">  
  3.   <complexType name="Person">  
  4.     <sequence>  
  5.       <element name="id1" type="long" minOccurs="0" nillable="true"/>  
  6.       <element name="id2" type="long" minOccurs="0" nillable="false"/>  
  7.       <element name="id3" type="long" minOccurs="1" nillable="true"/>  
  8.       <element name="id4" type="long" minOccurs="1" nillable="false"/>  
  9.       <element name="name1" type="string" minOccurs="0" nillable="true"/>  
  10.       <element name="name2" type="string" minOccurs="0" nillable="false"/>  
  11.       <element name="name3" type="string" minOccurs="1" nillable="true"/>  
  12.       <element name="name4" type="string" minOccurs="1" nillable="false"/><!--前面说的这个节点这么定义没有意义,为了实验的严谨性,依然保留-->  
  13.     </sequence>  
  14.   </complexType>  
  15.     
  16.   <complexType name="PersonRequest">  
  17.     <sequence>  
  18.       <element name="person" type="sys:Person"/>  
  19.     </sequence>  
  20.   </complexType>  
  21.   <complexType name="PersonResponse">  
  22.     <sequence>  
  23.       <element name="id" type="string" minOccurs="0"/>  
  24.     </sequence>  
  25.   </complexType>  
  26.     
  27.   <element name="GetPerson" type="sys:PersonRequest"></element>  
  28.   <element name="GetPersonResponse" type="sys:PersonResponse"></element>  
  29. </schema>  
  30. </span>  

和.net相比,此处多了一个类型PersonRequest,之所以改成这样是因为:如果按照net那种方式,生成的java代码中不会有Person类,因为工具认为id1,id2....是GetPerson的参数。

3.1.2 生成数据类
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#000000;">/** 
  2.  * Person.java 
  3.  * 
  4.  * This file was auto-generated from WSDL 
  5.  * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter. 
  6.  */  
  7.   
  8. package core.bank.csii.com.system;  
  9.   
  10. public class Person  implements java.io.Serializable {  
  11.     private java.lang.Long id1;  
  12.   
  13.     private java.lang.Long id2;  
  14.   
  15.     private java.lang.Long id3;  
  16.   
  17.     private long id4;  
  18.   
  19.     private java.lang.String name1;  
  20.   
  21.     private java.lang.String name2;  
  22.   
  23.     private java.lang.String name3;  
  24.   
  25.     private java.lang.String name4;  
  26.   
  27.     public Person() {  
  28.     }  
  29.   
  30.     public Person(  
  31.            java.lang.Long id1,  
  32.            java.lang.Long id2,  
  33.            java.lang.Long id3,  
  34.            long id4,  
  35.            java.lang.String name1,  
  36.            java.lang.String name2,  
  37.            java.lang.String name3,  
  38.            java.lang.String name4) {  
  39.            this.id1 = id1;  
  40.            this.id2 = id2;  
  41.            this.id3 = id3;  
  42.            this.id4 = id4;  
  43.            this.name1 = name1;  
  44.            this.name2 = name2;  
  45.            this.name3 = name3;  
  46.            this.name4 = name4;  
  47.     }  
  48.   
  49.   
  50.     /** 
  51.      * Gets the id1 value for this Person. 
  52.      *  
  53.      * @return id1 
  54.      */  
  55.     public java.lang.Long getId1() {  
  56.         return id1;  
  57.     }  
  58.   
  59.   
  60.     /** 
  61.      * Sets the id1 value for this Person. 
  62.      *  
  63.      * @param id1 
  64.      */  
  65.     public void setId1(java.lang.Long id1) {  
  66.         this.id1 = id1;  
  67.     }  
  68.   
  69.   
  70.     /** 
  71.      * Gets the id2 value for this Person. 
  72.      *  
  73.      * @return id2 
  74.      */  
  75.     public java.lang.Long getId2() {  
  76.         return id2;  
  77.     }  
  78.   
  79.   
  80.     /** 
  81.      * Sets the id2 value for this Person. 
  82.      *  
  83.      * @param id2 
  84.      */  
  85.     public void setId2(java.lang.Long id2) {  
  86.         this.id2 = id2;  
  87.     }  
  88.   
  89.   
  90.     /** 
  91.      * Gets the id3 value for this Person. 
  92.      *  
  93.      * @return id3 
  94.      */  
  95.     public java.lang.Long getId3() {  
  96.         return id3;  
  97.     }  
  98.   
  99.   
  100.     /** 
  101.      * Sets the id3 value for this Person. 
  102.      *  
  103.      * @param id3 
  104.      */  
  105.     public void setId3(java.lang.Long id3) {  
  106.         this.id3 = id3;  
  107.     }  
  108.   
  109.   
  110.     /** 
  111.      * Gets the id4 value for this Person. 
  112.      *  
  113.      * @return id4 
  114.      */  
  115.     public long getId4() {  
  116.         return id4;  
  117.     }  
  118.   
  119.   
  120.     /** 
  121.      * Sets the id4 value for this Person. 
  122.      *  
  123.      * @param id4 
  124.      */  
  125.     public void setId4(long id4) {  
  126.         this.id4 = id4;  
  127.     }  
  128.   
  129.   
  130.     /** 
  131.      * Gets the name1 value for this Person. 
  132.      *  
  133.      * @return name1 
  134.      */  
  135.     public java.lang.String getName1() {  
  136.         return name1;  
  137.     }  
  138.   
  139.   
  140.     /** 
  141.      * Sets the name1 value for this Person. 
  142.      *  
  143.      * @param name1 
  144.      */  
  145.     public void setName1(java.lang.String name1) {  
  146.         this.name1 = name1;  
  147.     }  
  148.   
  149.   
  150.     /** 
  151.      * Gets the name2 value for this Person. 
  152.      *  
  153.      * @return name2 
  154.      */  
  155.     public java.lang.String getName2() {  
  156.         return name2;  
  157.     }  
  158.   
  159.   
  160.     /** 
  161.      * Sets the name2 value for this Person. 
  162.      *  
  163.      * @param name2 
  164.      */  
  165.     public void setName2(java.lang.String name2) {  
  166.         this.name2 = name2;  
  167.     }  
  168.   
  169.   
  170.     /** 
  171.      * Gets the name3 value for this Person. 
  172.      *  
  173.      * @return name3 
  174.      */  
  175.     public java.lang.String getName3() {  
  176.         return name3;  
  177.     }  
  178.   
  179.   
  180.     /** 
  181.      * Sets the name3 value for this Person. 
  182.      *  
  183.      * @param name3 
  184.      */  
  185.     public void setName3(java.lang.String name3) {  
  186.         this.name3 = name3;  
  187.     }  
  188.   
  189.   
  190.     /** 
  191.      * Gets the name4 value for this Person. 
  192.      *  
  193.      * @return name4 
  194.      */  
  195.     public java.lang.String getName4() {  
  196.         return name4;  
  197.     }  
  198.   
  199.   
  200.     /** 
  201.      * Sets the name4 value for this Person. 
  202.      *  
  203.      * @param name4 
  204.      */  
  205.     public void setName4(java.lang.String name4) {  
  206.         this.name4 = name4;  
  207.     }  
  208.   
  209.     private java.lang.Object __equalsCalc = null;  
  210.     public synchronized boolean equals(java.lang.Object obj) {  
  211.         if (!(obj instanceof Person)) return false;  
  212.         Person other = (Person) obj;  
  213.         if (obj == nullreturn false;  
  214.         if (this == obj) return true;  
  215.         if (__equalsCalc != null) {  
  216.             return (__equalsCalc == obj);  
  217.         }  
  218.         __equalsCalc = obj;  
  219.         boolean _equals;  
  220.         _equals = true &&   
  221.             ((this.id1==null && other.getId1()==null) ||   
  222.              (this.id1!=null &&  
  223.               this.id1.equals(other.getId1()))) &&  
  224.             ((this.id2==null && other.getId2()==null) ||   
  225.              (this.id2!=null &&  
  226.               this.id2.equals(other.getId2()))) &&  
  227.             ((this.id3==null && other.getId3()==null) ||   
  228.              (this.id3!=null &&  
  229.               this.id3.equals(other.getId3()))) &&  
  230.             this.id4 == other.getId4() &&  
  231.             ((this.name1==null && other.getName1()==null) ||   
  232.              (this.name1!=null &&  
  233.               this.name1.equals(other.getName1()))) &&  
  234.             ((this.name2==null && other.getName2()==null) ||   
  235.              (this.name2!=null &&  
  236.               this.name2.equals(other.getName2()))) &&  
  237.             ((this.name3==null && other.getName3()==null) ||   
  238.              (this.name3!=null &&  
  239.               this.name3.equals(other.getName3()))) &&  
  240.             ((this.name4==null && other.getName4()==null) ||   
  241.              (this.name4!=null &&  
  242.               this.name4.equals(other.getName4())));  
  243.         __equalsCalc = null;  
  244.         return _equals;  
  245.     }  
  246.   
  247.     private boolean __hashCodeCalc = false;  
  248.     public synchronized int hashCode() {  
  249.         if (__hashCodeCalc) {  
  250.             return 0;  
  251.         }  
  252.         __hashCodeCalc = true;  
  253.         int _hashCode = 1;  
  254.         if (getId1() != null) {  
  255.             _hashCode += getId1().hashCode();  
  256.         }  
  257.         if (getId2() != null) {  
  258.             _hashCode += getId2().hashCode();  
  259.         }  
  260.         if (getId3() != null) {  
  261.             _hashCode += getId3().hashCode();  
  262.         }  
  263.         _hashCode += new Long(getId4()).hashCode();  
  264.         if (getName1() != null) {  
  265.             _hashCode += getName1().hashCode();  
  266.         }  
  267.         if (getName2() != null) {  
  268.             _hashCode += getName2().hashCode();  
  269.         }  
  270.         if (getName3() != null) {  
  271.             _hashCode += getName3().hashCode();  
  272.         }  
  273.         if (getName4() != null) {  
  274.             _hashCode += getName4().hashCode();  
  275.         }  
  276.         __hashCodeCalc = false;  
  277.         return _hashCode;  
  278.     }  
  279.   
  280.     // Type metadata  
  281.     private static org.apache.axis.description.TypeDesc typeDesc =  
  282.         new org.apache.axis.description.TypeDesc(Person.classtrue);  
  283.   
  284.     static {  
  285.         typeDesc.setXmlType(new javax.xml.namespace.QName("http://com.csii.bank.core/system""Person"));  
  286.         org.apache.axis.description.ElementDesc elemField = new org.apache.axis.description.ElementDesc();  
  287.         elemField.setFieldName("id1");  
  288.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""id1"));  
  289.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""long"));  
  290.         elemField.setMinOccurs(0);  
  291.         elemField.setNillable(true);  
  292.         typeDesc.addFieldDesc(elemField);  
  293.         elemField = new org.apache.axis.description.ElementDesc();  
  294.         elemField.setFieldName("id2");  
  295.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""id2"));  
  296.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""long"));  
  297.         elemField.setMinOccurs(0);  
  298.         elemField.setNillable(false);  
  299.         typeDesc.addFieldDesc(elemField);  
  300.         elemField = new org.apache.axis.description.ElementDesc();  
  301.         elemField.setFieldName("id3");  
  302.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""id3"));  
  303.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""long"));  
  304.         elemField.setNillable(true);  
  305.         typeDesc.addFieldDesc(elemField);  
  306.         elemField = new org.apache.axis.description.ElementDesc();  
  307.         elemField.setFieldName("id4");  
  308.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""id4"));  
  309.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""long"));  
  310.         elemField.setNillable(false);  
  311.         typeDesc.addFieldDesc(elemField);  
  312.         elemField = new org.apache.axis.description.ElementDesc();  
  313.         elemField.setFieldName("name1");  
  314.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""name1"));  
  315.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""string"));  
  316.         elemField.setMinOccurs(0);  
  317.         elemField.setNillable(true);  
  318.         typeDesc.addFieldDesc(elemField);  
  319.         elemField = new org.apache.axis.description.ElementDesc();  
  320.         elemField.setFieldName("name2");  
  321.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""name2"));  
  322.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""string"));  
  323.         elemField.setMinOccurs(0);  
  324.         elemField.setNillable(false);  
  325.         typeDesc.addFieldDesc(elemField);  
  326.         elemField = new org.apache.axis.description.ElementDesc();  
  327.         elemField.setFieldName("name3");  
  328.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""name3"));  
  329.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""string"));  
  330.         elemField.setNillable(true);  
  331.         typeDesc.addFieldDesc(elemField);  
  332.         elemField = new org.apache.axis.description.ElementDesc();  
  333.         elemField.setFieldName("name4");  
  334.         elemField.setXmlName(new javax.xml.namespace.QName("http://com.csii.bank.core/system""name4"));  
  335.         elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema""string"));  
  336.         elemField.setNillable(false);  
  337.         typeDesc.addFieldDesc(elemField);  
  338.     }  
  339.   
  340.     /** 
  341.      * Return type metadata object 
  342.      */  
  343.     public static org.apache.axis.description.TypeDesc getTypeDesc() {  
  344.         return typeDesc;  
  345.     }  
  346.   
  347.     /** 
  348.      * Get Custom Serializer 
  349.      */  
  350.     public static org.apache.axis.encoding.Serializer getSerializer(  
  351.            java.lang.String mechType,   
  352.            java.lang.Class _javaType,    
  353.            javax.xml.namespace.QName _xmlType) {  
  354.         return   
  355.           new  org.apache.axis.encoding.ser.BeanSerializer(  
  356.             _javaType, _xmlType, typeDesc);  
  357.     }  
  358.   
  359.     /** 
  360.      * Get Custom Deserializer 
  361.      */  
  362.     public static org.apache.axis.encoding.Deserializer getDeserializer(  
  363.            java.lang.String mechType,   
  364.            java.lang.Class _javaType,    
  365.            javax.xml.namespace.QName _xmlType) {  
  366.         return   
  367.           new  org.apache.axis.encoding.ser.BeanDeserializer(  
  368.             _javaType, _xmlType, typeDesc);  
  369.     }  
  370.   
  371. }</span>  
java生成的Person类没有Specified属性,看来它只支持一种形式,下面进行验证
3.2.3查看SOAP报文
java代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. Person p=new Person();  
  2. p.setId1(null);  
  3. p.setId2(null);  
  4. p.setId3(null);  
  5. p.setId4(0);  
  6. p.setName1(null);  
  7. p.setName2(null);  
  8. p.setName3(null);  
  9. p.setName4("123");//.NET实验时,name4传的是null;但如果此处赋null,报文还未发出去,客户端框架就报错:提示不能为null了。  
Soap报文:
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">  
  3.   <soapenv:Body>  
  4.     <GetSystemStatus xmlns="http://com.csii.bank.core/system">  
  5.       <person>  
  6.         <id3 xsi:nil="true"/>  
  7.         <id4>0</id4>  
  8.         <name3 xsi:nil="true"/>  
  9.         <name4>123</name4>  
  10.       </person>  
  11.     </GetSystemStatus>  
  12.   </soapenv:Body>  
  13. </soapenv:Envelope>  

3.2.4 得出结论:
其一:对于值类型和包装:
  1、除 [ minOccurs=1,nillable=false ] 这一组合除外,生成的都是包装类型。
  2、当对象属性为null时,java根据minOccurs构造soap报文,如果minOccurs=0则[元素节点]不出现代表null,如果minOccurs=1用nil=true表示null。
其二:对于普通引用类型
  生成的肯定是引用类型(这是废话),当对象属性为null是,构造soap报文的规则和上面的2一样
4、深入浅出,最后的总结
不管是由代码生成wsdl,还是由wsdl生成代码,此实验中java都比.NET要简洁,个人比较喜欢java的方式,.NET显得有点儿啰嗦(它把包装类型和普通引用类型做了区分),下面进行最后的总结。
先来总结由代码生成wsdl
java用到了两种组合:
   [minOccurs=1、
nillable=false]:只有值类型用这一组合
   [minOccurs=1、
nillable=true]:包装类型和普通引用类型用这一组合
   注:其实Java用[minOccurs=0 和nillable=false]代表包装类型和普通引用类型也完全可以,如果是我的话我会用这一组合代替上面的组合,这样可以节省网络流量
而.NET有3种组合:
   [ minOccurs=1、nillable=false]:只有值类型用这一组合
   [ minOccurs=1、nillable=true ] :包装类型用这一组合
   [ minOccurs=0、nillable=false]:普通引用类型用这一组合
现在如果要我们自己写一个生成wsdl的框架,那应该有如下的原则:
   1>  值类型只能
[minOccurs=1、nillable=false],而包装类型和普通引用类型不能用这一组合(否则空对象无法表示)
 
   
2>  包装类型可以用[minOccurs=1、nillable=true]和[ minOccurs=0、nillable=false]
  3> 普通引用类型可以
[minOccurs=1、nillable=true]和[ minOccurs=0、nillable=false]
  
4> 对于包装类型和普通引用类型不建议用[minOccurs=0、nillable=true],这一组合意义不够明确,究竟是空报文节点表示null呢?还是nill=true表示null呢?当然如果真这么用肯定也没问题,只要序列化工具支持就行。

再来看由wsdl生成代码
我是很难理解微软为什么要把[包装类型]和[普通引用类型]区别对待,在C#_2_WSDL的时候这么区别开到还没什么,但是当WSDL_2_C#的时候就带来很大的麻烦。
1、首先来看<element name="long" type="dateTime" minOccurs="0" nillable="false"/>,对这一组合微软生成的是值类型而不是包装类型,它认为只有nillable=true才代表包装类型,可包装类型和普通引用类型本质上有太大的区别吗?大家都是引用类型,[minOccurs=1、nillable=true]和[ minOccurs=0、nillable=false]应该都可以被解析为包装类型才合适。你微软如果认为nillable=true和包装类型(微软的可空类型)联系那么紧密,那这样的节点<element name="name3" type="string" minOccurs="1" nillable="true"/>最好还是别支持了,但现在普通应用类型你既支持minOccurs=0又支持nillable=true,那包装类型和普通引用类型分开的必要性究竟是神马!!!!!!
2、再来看xxxSpecified,前面说到,微软认为对于像type=int这样的节点,如果element定义中出现了minOccurs=0,则要生成一个xxxSpecified属性。这么搞使用起来简直太麻烦了——让程序员指定xxxSepcified为true或false来控制元素节点要不要显示,这种麻烦还是由于“区别对待”带来的。微软只通过nillable判断是否是包装类型,对于minOccurs=0的情况它不得不生成一个xxxSpecified。而如果不区别对待的话就简单多了,只要minOccurs=0和nillable=true随便哪个出现或同时出现,直接生成包装类型。

最后来总结序列化

序列化的时候,java和.NET在处理上也不尽相同:
1、java优先考虑minOccurs,如果minOccurs=0,那不管nillable等于神马,程序中的null以[元素节点]不出现的方式来体现;如果minOccurs=1,则程序中的null以[元素取值]为空的方式来体现;这样的规则同时适用于值类型、包装类型和普通引用类型。
2、而.NET则优先考虑nillable,如果nillable=true,那不管minOccurs等于神马,程序中的null以[元素取值]为空的方式来体现;如果nillable=false,则程序中的null以[元素节点]不出现的方式来体现;这样的规则同时适用于值类型、包装类型和普通引用类型。(注:Specified=true的前提下






2
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: .NET Web服务是一种基于标准的Web服务架构,它使用SOAP(简单对象访问协议)和WSDL(Web服务描述语言)来实现跨平台和跨语言的通信。WSDL是一种XML格式的文档,它定义了WebService的接口和数据类型。 在.NET中,我们可以使用WebService语言来创建和发布Web服务。在创建和发布Web服务时,我们需要使用WSDL。通过WSDL,我们可以定义WebService的接口以及它所使用的数据类型和操作。WSDL描述了WebService的详细信息,包括它的地址、端口、传输协议等。 在客户端使用Web服务时,我们可以通过WSDL从Web服务中获取接口和数据类型的描述信息。通过WSDL,客户端可以了解到Web服务提供的功能、接收的参数类型以及返回的结果类型。这使得客户端可以根据Web服务的描述信息生成相应的客户端代理类,并利用该代理类与Web服务进行交互。 另外,通过WSDL,不仅可以对Web服务进行动态调用,还可以支持工具自动生成代码,以便于客户端使用。通过解析WSDL文档,我们可以生成相应的服务类和客户端代理类,从而简化了Web服务的调用过程。 总而言之,WSDL.NET Web服务中扮演着非常重要的角色,它用于定义Web服务的接口和数据类型,并提供了客户端生成所需代码的便利。通过WSDL,我们可以更好地理解和使用Web服务,实现跨平台和跨语言的通信。 ### 回答2: .NET Web Service是一种使用SOAP(简单对象访问协议)协议和WSDL(Web 服务描述语言)定义和创建的跨平台、跨语言的网络服务。WSDL是一种用于描述Web服务的XML格式文件。 .NET Web Service的WSDL文件包含了服务的端点、方法、参数、返回类型等详细信息。通过阅读WSDL文件,客户端可以了解到Web服务的功能和使用方式。 WSDL文件中定义了服务的接口以及与之交互的消息格式。客户端可以通过解析WSDL文件来生成对应的客户端代理类,从而能够与Web服务进行交互。客户端代理类将根据WSDL文件中的定义自动处理SOAP消息的生成、解析和传输,并将接收到的结果转换为本地对象,方便客户端使用。 使用WSDL可以实现不同语言和平台之间的互操作性。在不同的开发环境中,可以使用不同的工具来解析WSDL文件,生成相应的客户端代理类。这样,无论是使用.NETJava、Python还是其他语言,都可以方便地调用相同的Web服务。 总之,.NET Web Service的WSDL文件是描述Web服务的重要文件,它定义了服务接口和消息格式,提供了与服务交互的详细信息。通过解析WSDL文件,客户端可以生成对应的客户端代理类,实现与Web服务的交互。同时,WSDL还提供了平台和语言无关的特性,使得跨平台和跨语言的互操作性成为可能。 ### 回答3: .NET Web服务描述语言(WSDL)是一种XML格式的文件,用于描述提供的Web服务的接口和操作。它提供了一种标准的方式来定义Web服务的输入、输出和方法。 首先,WSDL文件是Web服务的服务描述文件。它定义了Web服务的地址、命名空间、方法、输入参数和输出结果等信息。通过查看WSDL文件,客户端可以了解Web服务的功能和可用方法。 WSDL文件通常包含以下几个部分: 1. 服务描述:描述了服务的地址和命名空间。 2. 数据类型定义:定义了Web服务的输入和输出数据类型,包括简单类型和复杂类型。 3. 端口类型定义:定义了Web服务的接口,包括方法的名称、输入参数和输出结果。 4. 绑定定义:将端口类型和传输协议(如SOAP、HTTP)进行绑定。 5. 服务定义:定义了Web服务的名称、端口和绑定。 客户端可以使用WSDL文件来生成Web服务的客户端代理类,以便在编程过程中调用Web服务的方法。通过生成的客户端代理类,客户端可以轻松地与Web服务进行通信、发送请求和接收响应。 WSDL文件还可以用于Web服务的自动化工具和集成开发环境(IDE)的集成。这样,开发人员可以更方便地创建和开发基于Web服务的应用程序。 总之,.NET Web服务描述语言(WSDL)是一种用于描述Web服务接口和操作的标准格式。它可以帮助客户端了解和使用Web服务,并提供了一种自动生成客户端代理类的方便方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值