国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
WebService對(duì)象可空的困惑,關(guān)于nillable和minOccurs

術(shù)語(yǔ)約定
文章中會(huì)反復(fù)出現(xiàn)[值類型]、[包裝類型]、[普通引用類型]、[元素節(jié)點(diǎn)]和[元素取值]的表述
1> [值類型]指的是java和.NET中的基本數(shù)據(jù)類型,如:int;
2> [包裝類型]指的是java中的包裝類和.NET中的Nullable<T>類型,如:Integer、int?;
3> [普通引用類型]指的是除包裝類型外的其它引用類型;
4> [元素節(jié)點(diǎn)]指的是xml文檔中的一個(gè)標(biāo)簽節(jié)點(diǎn),我們可以說[元素節(jié)點(diǎn)]是必輸還是非必輸,如:<Name>lubiao</Name>;
5> [元素取值]指的是xml標(biāo)簽節(jié)點(diǎn)的內(nèi)容,我們可以說[元素取值]是空還是非空,如:<Name>lubiao</Name>表示元素取值不為空,<Name xsi:nil="true"/>表示元素取值為空;

1、首先來看minOccurs和Nillable的定義
minOccurs
:表示XML文檔中某個(gè)[元素節(jié)點(diǎn)] 是否可以不出現(xiàn),默認(rèn)值為1,表示必須出現(xiàn)
nillable:表示XML文檔中某個(gè)[元素取值] 是否可以為空(形如:<name xsi:nil="true" />),默認(rèn)值為false,表示不能為空
那么,minOccurs和nillable的組合形式就會(huì)有4種,如下:
例一,值類型:

  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"/>  

例二,引用類型:

  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自動(dòng)生成WSDL的規(guī)則
在實(shí)際開發(fā)時(shí)我們通常的做法是先編寫Server端代碼,然后利用工具自動(dòng)生成wsdl描述,最后再利用工具讀取wsdl進(jìn)而生成客戶端程序。那么用工具生成wsdl和用工具反向生成代理程序的規(guī)則是什么呢?下來對(duì)此進(jìn)行實(shí)例分析:
2.1 先看.NET生成wsdl的規(guī)則
實(shí)驗(yàn)時(shí)所用的開發(fā)工具為VS 2010,用vs開發(fā)WebService的資料,百度搜索一大推,這里不贅述。
2.1.1、定義數(shù)據(jù)實(shí)體:Person.cs

  1. public class Person   
  2. {  
  3.     public int Id { get; set; } //值類型  
  4.     public string Name { get; set; }//普通引用類型  
  5.     public int? PhoneNbr { get; set; }//包裝類型  
  6. }  

2.1.2、定義服務(wù)類:WebService.cs

  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.        //如果使用設(shè)計(jì)的組件,請(qǐng)取消注釋以下行   
  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個(gè)參數(shù),前三個(gè)參數(shù)和Person類的三個(gè)屬性是一樣的,加入這三個(gè)參數(shù)的目的是進(jìn)行對(duì)比測(cè)試。
2.1.3、查看生成的wsdl

  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默認(rèn)為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默認(rèn)為false,minOccurs等于0:即name元素為非必輸,但值不能為空-->  
  14.             <s:element minOccurs="0" maxOccurs="1" name="person" type="tns:Person" />  
  15.             <!--nillable默認(rèn)為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默認(rèn)為false,minOccurs默認(rèn)為1:即id元素為必輸,且值不能為空-->  
  23.           <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string" />  
  24.           <!--nillable默認(rèn)為false,minOccurs等于0:即Name元素為非必輸,但值不能為空-->  
  25.           <s:element minOccurs="1" maxOccurs="1" name="PhoneNbr" nillable="true" type="s:int" />  
  26.           <!--nillable默認(rèn)為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、得出結(jié)論  
*
id參數(shù)和Person.Id屬性都為值類型:[元素節(jié)點(diǎn)] 都必輸,[元素取值] 都不能為空
* phoneNbr參數(shù)和Person.PhoneNbr屬性都是包裝類型:[元素節(jié)點(diǎn)] 都必輸,但[元素取值] 都可以為空;
* name參數(shù)和Person.Name屬性都是普通引用類型:[元素節(jié)點(diǎn)] 都可以不輸,但[元素取值] 都不能為空;
* person參數(shù)是普通引用類型:[元素節(jié)點(diǎn)] 可以不輸,但[元素取值] 不能為空。
2.2 再看Java的規(guī)則
首先,先熟悉在eclipse中快速開發(fā)webservice程序的步驟,參考鏈接:http://www.blogjava.net/parable-myth/archive/2010/08/03/327802.html,此次實(shí)驗(yàn)采用的就是這種快速開發(fā)方式(注:不同的框架和工具會(huì)可能會(huì)有不同的生成規(guī)則),所用ecllipse版本為:
    Version: Juno Service Release 1
    Build id: 20121004-1855
2.2.1、定義數(shù)據(jù)實(shí)體:Person.java

  1. package com.lubiao.axis;  
  2.   
  3. public class Person  implements java.io.Serializable {  
  4.     private int id;//編號(hào),值類型  
  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、定義服務(wù)類:WebServiceTest.java

  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個(gè)參數(shù),前三個(gè)參數(shù)和Person類的三個(gè)屬性是一樣的,加入這三個(gè)參數(shù)的目的是進(jìn)行對(duì)比測(cè)試。
2.2.3、查看生成的Wsdl

  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默認(rèn)為false,minOccurs默認(rèn)為1:即id元素為必輸,且值不能為空-->  
  11.             <element name="phoneNbr" type="xsd:int"/>  
  12.             <!--nillable默認(rèn)為false,minOccurs默認(rèn)為1:即phoneNbr元素為必輸,且值不能為空-->  
  13.             <element name="name" type="xsd:string"/>  
  14.             <!--nillable默認(rèn)為false,minOccurs默認(rèn)為1:即name元素為必輸,且值不能為空-->  
  15.             <element name="person" type="impl:Person"/>  
  16.             <!--nillable默認(rèn)為false,minOccurs默認(rèn)為1:即person元素為必輸,且值不能為空-->  
  17.           </sequence>  
  18.         </complexType>  
  19.       </element>  
  20.       <complexType name="Person">  
  21.         <sequence>  
  22.           <element name="id" type="xsd:int"/>  
  23.           <!--nillable默認(rèn)為false,minOccurs默認(rèn)為1:即id元素為必輸,且值不能為空-->  
  24.           <element name="name" nillable="true" type="xsd:string"/>  
  25.           <!--nillable默認(rèn)為true,minOccurs默認(rèn)為1:即name元素為必輸,但值可以為空-->  
  26.           <element name="phoneNbr" nillable="true" type="xsd:int"/>  
  27.           <!--nillable默認(rèn)為true,minOccurs默認(rèn)為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、得出結(jié)論
* id參數(shù)和Person.id屬性都是值類型:[元素節(jié)點(diǎn)] 都必輸,[元素取值] 都不能為空;
* phoneNbr參數(shù)和Person.phoneNbr屬性都是包裝類型:[元素節(jié)點(diǎn)] 都必輸,但前者[元素取值]不能為空,后者[元素取值]可以為空;
* name參數(shù)和Person.name屬性都是普通的引用類型:[元素節(jié)點(diǎn)] 都必輸,但前者[元素取值]不能為空,后者[元素取值]可以為空;
* person參數(shù)屬于普通引用類型:[元素節(jié)點(diǎn)]必輸,且[元素取值]不能為空;
*總結(jié):此框架生成wsdl時(shí)認(rèn)為:
        1、作為方法參數(shù)時(shí),不管是值類型、包裝類型還是普通引用類型,[元素節(jié)點(diǎn)]都為必輸項(xiàng),且[元素取值]都不能為空;
        2、作為對(duì)象屬性時(shí),不管是值類型、包裝類型還是普通引用類型,[元素節(jié)點(diǎn)]都為必輸項(xiàng),其中值類型的[元素取值]不能為空,但包裝類型和普通引用類型的[元素取值]可以為空。

2.3、Java和.NET的異同
其一,對(duì)于值類型:
            Java和.NET都認(rèn)為值類型不論是作為 [方法參數(shù)時(shí)] 還是 [對(duì)象屬性時(shí)] ,[元素節(jié)點(diǎn)]都為必輸項(xiàng),且[元素取值]都不能為空。
             (都合理:這符合值類型的特點(diǎn),總有一個(gè)值)
其二,對(duì)于包裝類型:
            作為方法參數(shù)時(shí):java和.NET都認(rèn)為[元素節(jié)點(diǎn)]是必輸?shù)?,但java認(rèn)為[元素取值]不能為空,而.NET認(rèn)為[元素取值]可以為空;
               (.NET合理,Java不合理。java既要求必輸又要求值不能為空,那空對(duì)象怎么傳入?可以通過生成客戶端代理進(jìn)行驗(yàn)證(這里不再演示),對(duì)于phoneNbr參數(shù)客戶端代碼變成了int類型,而服務(wù)端可是Integer類型)
            作為對(duì)象屬性時(shí):java和.NET都認(rèn)為[元素是節(jié)點(diǎn)]必輸?shù)模鳾元素取值]是可以為空的;
                (都合理。java和.net都要求節(jié)點(diǎn)必須出現(xiàn),然后以nillable=true標(biāo)識(shí)可以傳入空值)
其三,對(duì)于普通引用類型:
            作為方法參數(shù)時(shí):java和.NET都認(rèn)為[元素取值]是不能為空的,但Java同時(shí)認(rèn)為[元素節(jié)點(diǎn)]是必輸?shù)?,?NET認(rèn)為[元素節(jié)點(diǎn)]是非必輸?shù)模?br>                (.NET合理,Java不合理。java既要求節(jié)點(diǎn)必輸還要求值不能為空,那空對(duì)象怎么傳入?)
            
作為對(duì)象屬性時(shí):java認(rèn)為[元素節(jié)點(diǎn)]是必輸?shù)?、[元素取值]是可空的;.NET認(rèn)為[元素節(jié)點(diǎn)]是非必輸?shù)?、[元素取值]是不可空的。
                (都合理。java始終要求必輸,但以nillable=true標(biāo)識(shí)可以傳入空對(duì)象;.NET始終要求元素取值不能為空,但以minOccurs=0來標(biāo)識(shí)可以傳入空對(duì)象)
總結(jié):
作為參數(shù)時(shí),java出現(xiàn)了很多不合理的情況,可能是因?yàn)檫x的這個(gè)框架有bug,這里不再關(guān)心,主要看作為對(duì)象屬性時(shí)的情況。文章最開始的時(shí)候說到minOccurs和nillable會(huì)有4種組合方式,在上面的實(shí)驗(yàn)中java用到了兩種,而.NET用到了3種,分別為:
Java:[ minOccurs=1,nillable=false ] 和 [ minOccurs=1,nillable=true ],前者對(duì)應(yīng)值類型,后者對(duì)應(yīng)引用類型(包裝類型和普通引用類型),java壓根沒用minOccrs=0
.NET:[ minOccurs=1,nillable=false ]、[ minOccurs=1,nillable=true ] 和[ minOccurs=0,nillable=false],前者對(duì)應(yīng)值類型,再者對(duì)應(yīng)包裝類型,最后對(duì)應(yīng)普通引用類型。
3、Java和.NET由WSDL自動(dòng)生成代碼的規(guī)則
接著上面的實(shí)驗(yàn)結(jié)果,先來做最簡(jiǎn)單的測(cè)試:1、用java的client對(duì)接java的service生成代碼;2、用.NET的client對(duì)接.NET的Service生成代碼,然后分別觀察Client端自動(dòng)生成的Person類和Server段的Person是否完全一致。這里不再演示,只說結(jié)論,結(jié)論是:生成的Person分別和各自Server端的完全相同。
那如果用[ java對(duì)接.NET ] 或者[ 用.NET對(duì)接java ],會(huì)是什么結(jié)果呢?等一等,這么問好像有問題,哪有什么誰對(duì)接誰,大家對(duì)接的都是wsdl,哪里知道wsdl后面是什么平臺(tái)?。∴?,那就把minOccurs和nillable的四種組合都列出來,看java和.NET的生成規(guī)則分別是什么樣的,繼續(xù)。
3.1 先看.NET的規(guī)則
3.1.1 定義WSDL,限于篇幅只列出類型定義部分

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <schema xmlns="<a target="_blank" ></element>  
  3. </schema>  

id對(duì)應(yīng)的是值類型,name對(duì)應(yīng)的是引用類型
3.1.2 生成數(shù)據(jù)類

  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、生成了對(duì)應(yīng)的id1Specified
id2:值類型、特性:IsNullable=false、生成了對(duì)應(yīng)的id2Specified
id3:可空類型、特性:IsNullable=true
id4:值類型、特性:IsNullable=false
name1:引用類型、特性:IsNullable=true
name2:引用類型、特性:IsNullable=false
name3:引用類型、特性:IsNullable=true
name4:引用類型、特性:IsNullable=false
3.1.3 查看SOAP報(bào)文
將可為null的屬性都置位null,然后查看SOAP報(bào)文是什么樣子的
C#代碼1:

  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:

  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報(bào)文1:對(duì)應(yīng)C#代碼1,只貼出Person部分:

  1. <Person>  
  2.       <id3 xsi:nil="true" />  
  3.       <id4>456</id4>  
  4.       <name1 xsi:nil="true" />  
  5.       <name3 xsi:nil="true" />  
  6. </Person>  

SOAP報(bào)文2:對(duì)應(yīng)C#代碼2,只貼出Person部分:

  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 得出結(jié)論
其一:對(duì)于值類型和包裝類型

minOccurs="0" 組合nillable="true"時(shí)
會(huì)生成包裝類型(id1),同時(shí)會(huì)生成對(duì)應(yīng)的id1Specified屬性,為什么會(huì)生成帶Specified的屬性呢?這是因?yàn)閙inOccurs="0"的緣故,minOccurs=0意味著元素節(jié)點(diǎn)可以不出現(xiàn),那到底是出現(xiàn)呢?還是不出現(xiàn)呢?工具自己沒了主意,所以生成了一個(gè)xxxSpecified屬性,該屬性默認(rèn)值為false,只有給它指定true的時(shí)候[元素節(jié)點(diǎn)]才會(huì)出現(xiàn)到soap報(bào)文中。
minOccurs="0"組合nillable="false"時(shí)
會(huì)生成值類型(id2),同時(shí)會(huì)生成對(duì)應(yīng)的id2Specified屬性(原因同上)
minOccurs="1" 組合nillable="true"時(shí)
會(huì)生成包裝(id3),不會(huì)生成Specified屬性(因?yàn)樵毓?jié)點(diǎn)必輸)。
minOccurs=“1”組合nillable=“false”時(shí)
會(huì)生成值類型(id4),不會(huì)生成Specified屬性(因?yàn)樵毓?jié)點(diǎn)必輸)。
其二:對(duì)于普通引用類型
name1、name3:
只要nillable=true不管minOccurs等于什么,[null對(duì)象]序列化的時(shí)候都以[元素取值]為空方式來體現(xiàn)這是一個(gè)空對(duì)象。
name2、name4:   
只要nillable=false不管minOccurs等于什么,[null對(duì)象]序列化時(shí)都以[元素節(jié)點(diǎn)]不出現(xiàn)的方式來體現(xiàn)這是一個(gè)空對(duì)象。(上面實(shí)驗(yàn)時(shí),Server端對(duì)soap報(bào)文進(jìn)行了schema驗(yàn)證,所以name4傳null會(huì)報(bào)錯(cuò)的)

總結(jié):
* .NET在wsdl_2_C# 和C#_2_wsdl時(shí)的思路其實(shí)是一致的,1、生成值類型還是包裝類型先看nillable屬性、然后再看minOccurs屬性來控制是否生成xxxSpecified屬性;2、而生成普通引用類型時(shí)只關(guān)心nillable屬性,nillable=true就采用nil=true的方式發(fā)送null對(duì)象,nillabe=false則采用[元素節(jié)點(diǎn)]不出現(xiàn)的方式發(fā)送null對(duì)象,壓根就不關(guān)心minOccurs是神馬。
* 前面說到name4=null時(shí),Server端會(huì)報(bào)錯(cuò),所以 對(duì)于引用類型:minOccurs=1和nillable=false的組合是沒有意義的,這種組合無法讓空對(duì)象傳輸過來
3.2 再看Java的規(guī)則

3.2.1 定義WSDL,限于篇幅只列出類型定義部分
  1. <span style="color:#000000;"><?xml version="1.0" encoding="UTF-8"?>  
  2. <schema xmlns="<a target="_blank" ></element>  
  3. </schema>  
  4. </span>  

和.net相比,此處多了一個(gè)類型PersonRequest,之所以改成這樣是因?yàn)椋喝绻凑課et那種方式,生成的java代碼中不會(huì)有Person類,因?yàn)楣ぞ哒J(rèn)為id1,id2....是GetPerson的參數(shù)。

3.1.2 生成數(shù)據(jù)類
  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 == null) return 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.class, true);  
  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屬性,看來它只支持一種形式,下面進(jìn)行驗(yàn)證
3.2.3查看SOAP報(bào)文
java代碼:

  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實(shí)驗(yàn)時(shí),name4傳的是null;但如果此處賦null,報(bào)文還未發(fā)出去,客戶端框架就報(bào)錯(cuò):提示不能為null了。  
Soap報(bào)文:
  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 得出結(jié)論:
其一:對(duì)于值類型和包裝:
  1、除 [ minOccurs=1,nillable=false ] 這一組合除外,生成的都是包裝類型。
  2、當(dāng)對(duì)象屬性為null時(shí),java根據(jù)minOccurs構(gòu)造soap報(bào)文,如果minOccurs=0則[元素節(jié)點(diǎn)]不出現(xiàn)代表null,如果minOccurs=1用nil=true表示null。
其二:對(duì)于普通引用類型
  生成的肯定是引用類型(這是廢話),當(dāng)對(duì)象屬性為null是,構(gòu)造soap報(bào)文的規(guī)則和上面的2一樣
4、深入淺出,最后的總結(jié)
不管是由代碼生成wsdl,還是由wsdl生成代碼,此實(shí)驗(yàn)中java都比.NET要簡(jiǎn)潔,個(gè)人比較喜歡java的方式,.NET顯得有點(diǎn)兒?jiǎn)拢ㄋ寻b類型和普通引用類型做了區(qū)分),下面進(jìn)行最后的總結(jié)。
先來總結(jié)由代碼生成wsdl
java用到了兩種組合:
   [minOccurs=1、
nillable=false]:只有值類型用這一組合
   [minOccurs=1、
nillable=true]:包裝類型和普通引用類型用這一組合
   注:其實(shí)Java用[minOccurs=0 和nillable=false]代表包裝類型和普通引用類型也完全可以,如果是我的話我會(huì)用這一組合代替上面的組合,這樣可以節(jié)省網(wǎng)絡(luò)流量
而.NET有3種組合:
   [ minOccurs=1、nillable=false]:只有值類型用這一組合
   [ minOccurs=1、nillable=true ] :包裝類型用這一組合
   [ minOccurs=0、nillable=false]:普通引用類型用這一組合
現(xiàn)在如果要我們自己寫一個(gè)生成wsdl的框架,那應(yīng)該有如下的原則:
   1>  值類型只能
[minOccurs=1、nillable=false],而包裝類型和普通引用類型不能用這一組合(否則空對(duì)象無法表示)
 
   
2>  包裝類型可以[minOccurs=1、nillable=true]和[ minOccurs=0、nillable=false]
  3> 普通引用類型可以
[minOccurs=1、nillable=true]和[ minOccurs=0、nillable=false]
 
4> 對(duì)于包裝類型和普通引用類型不建議用[minOccurs=0、nillable=true],這一組合意義不夠明確,究竟是空?qǐng)?bào)文節(jié)點(diǎn)表示null呢?還是nill=true表示null呢?當(dāng)然如果真這么用肯定也沒問題,只要序列化工具支持就行。

再來看由wsdl生成代碼
我是很難理解微軟為什么要把[包裝類型]和[普通引用類型]區(qū)別對(duì)待,在C#_2_WSDL的時(shí)候這么區(qū)別開到還沒什么,但是當(dāng)WSDL_2_C#的時(shí)候就帶來很大的麻煩。
1、首先來看<element name="long" type="dateTime" minOccurs="0" nillable="false"/>,對(duì)這一組合微軟生成的是值類型而不是包裝類型,它認(rèn)為只有nillable=true才代表包裝類型,可包裝類型和普通引用類型本質(zhì)上有太大的區(qū)別嗎?大家都是引用類型,[minOccurs=1、nillable=true]和[ minOccurs=0、nillable=false]應(yīng)該都可以被解析為包裝類型才合適。你微軟如果認(rèn)為nillable=true和包裝類型(微軟的可空類型)聯(lián)系那么緊密,那這樣的節(jié)點(diǎn)<element name="name3" type="string" minOccurs="1" nillable="true"/>最好還是別支持了,但現(xiàn)在普通應(yīng)用類型你既支持minOccurs=0又支持nillable=true,那包裝類型和普通引用類型分開的必要性究竟是神馬?。。。。?!
2、再來看xxxSpecified,前面說到,微軟認(rèn)為對(duì)于像type=int這樣的節(jié)點(diǎn),如果element定義中出現(xiàn)了minOccurs=0,則要生成一個(gè)xxxSpecified屬性。這么搞使用起來簡(jiǎn)直太麻煩了——讓程序員指定xxxSepcified為true或false來控制元素節(jié)點(diǎn)要不要顯示,這種麻煩還是由于“區(qū)別對(duì)待”帶來的。微軟只通過nillable判斷是否是包裝類型,對(duì)于minOccurs=0的情況它不得不生成一個(gè)xxxSpecified。而如果不區(qū)別對(duì)待的話就簡(jiǎn)單多了,只要minOccurs=0和nillable=true隨便哪個(gè)出現(xiàn)或同時(shí)出現(xiàn),直接生成包裝類型。

最后來總結(jié)序列化

序列化的時(shí)候,java和.NET在處理上也不盡相同:
1、java優(yōu)先考慮minOccurs,如果minOccurs=0,那不管nillable等于神馬,程序中的null以[元素節(jié)點(diǎn)]不出現(xiàn)的方式來體現(xiàn);如果minOccurs=1,則程序中的null以[元素取值]為空的方式來體現(xiàn);這樣的規(guī)則同時(shí)適用于值類型、包裝類型和普通引用類型。
2、而.NET則優(yōu)先考慮nillable,如果nillable=true,那不管minOccurs等于神馬,程序中的null以[元素取值]為空的方式來體現(xiàn);如果nillable=false,則程序中的null以[元素節(jié)點(diǎn)]不出現(xiàn)的方式來體現(xiàn);這樣的規(guī)則同時(shí)適用于值類型、包裝類型和普通引用類型。(注:Specified=true的前提下






本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
nillable與minOccurs
Web 服務(wù)技巧: XML Schema 中空值的表示
System.Xml 命名空間
技術(shù)文章-關(guān)于ESB的開發(fā)實(shí)踐小結(jié)
VB 6.0用SOAP去訪問Webservice
Schema和DTD的區(qū)別,驗(yàn)證XLM數(shù)據(jù)合法性...
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服