<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    happyfish

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      38 Posts :: 1 Stories :: 62 Comments :: 0 Trackbacks
    非.NET語言調(diào)用.NET XML Web Services返回的數(shù)據(jù)集合的兩個(gè)方法
    作者:鄭子穎
    摘要
    本文介紹了如何在非.NET語言環(huán)境中(如Java、Delphi等)調(diào)用.NET XML Web Services,并特別針對(duì)很多開發(fā)者所關(guān)心的"如何在Java/Delphi中使用.NET的Web Service返回的DataSet"的問題,提出了兩個(gè)解決方案:使用自定義類型數(shù)組和使用DataSet.WriteXML()。

    目錄
    • 1. 概述
    • 2. 創(chuàng)建.NET Web Services,返回?cái)?shù)據(jù)集合
    • 3. 在Java中調(diào)用.NET Web Services,處理返回的數(shù)據(jù)集合
    • 4. 小結(jié)

    1.概述
    很多正在開發(fā)或者打算開發(fā)XML Web Services的程序員都問過這樣的一個(gè)問題:"我的Web Service返回的結(jié)果是一個(gè)DataSet類型的對(duì)象,但如果我的客戶端不是用.NET寫的(因而沒有內(nèi)建的DataSet類型),那該如何調(diào)用這個(gè)Web Service并訪問DataSet中的數(shù)據(jù)呢?"。
    對(duì)于這個(gè)問題,首先應(yīng)該說的是:1)在多種語言共存的編程環(huán)境下,是不適合使用類似DataSet這種只屬于特定語言的數(shù)據(jù)類型的。不管是在XML Web Services還是CORBA的環(huán)境中,都應(yīng)該盡量使用簡單數(shù)據(jù)類型以及簡單數(shù)據(jù)類型的數(shù)組。2)應(yīng)當(dāng)很謹(jǐn)慎的決定是否需要通過
    Web Service來返回大量數(shù)據(jù)。由于網(wǎng)絡(luò)傳輸?shù)拈_銷既包括HTTP連接建立的時(shí)間,也包括傳送數(shù)據(jù)的時(shí)間,因此需要在減少訪問服務(wù)器次數(shù)和減少網(wǎng)絡(luò)傳輸量之間尋找一個(gè)合適的平衡。如非必須,則不適合通過Web Service傳送含有幾十條或者幾百條數(shù)據(jù)的數(shù)據(jù)表。
    然后,就問題本身而言,.NET Web Services返回的DataSet類型是可以直接被其他非.NET的客戶端解析的,因?yàn)榧幢闶荄ataSet類型的返回值,也會(huì)被表達(dá)成XML格式再進(jìn)行傳輸。下面的例子就是一個(gè)返回類型為DataSet的Web Method,及其被調(diào)用后返回的XML格式數(shù)據(jù):
    [WebMethod]
    public DataSet GetPersonData()
    {
    	DataTable table=new DataTable("Person");		
    	table.Columns.Add("Name");
    	table.Columns.Add("Gender");
    	table.Rows.Add(new string[2]{"Alice","Female"});
    	table.Rows.Add(new string[2]{"Bob","Male"});
    	table.Rows.Add(new string[2]{"Chris","Male"});
    				
    	DataSet dataset=new DataSet("PersonTable");
    	dataset.Tables.Add(table);
             return dataset;
    }
    
    圖表1. 返回類型為DataSet的Web Method
    <?xml version="1.0" encoding="utf-8"?>
    <DataSet xmlns="http://tempuri.org/">
      <xs:schema id="PersonTable" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    	xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
        <xs:element name="PersonTable" msdata:IsDataSet="true" msdata:Locale="zh-CN">
          <xs:complexType>
            <xs:choice maxOccurs="unbounded">
              <xs:element name="Person">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Name" type="xs:string" minOccurs="0" />
                    <xs:element name="Gender" type="xs:string" minOccurs="0" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:choice>
          </xs:complexType>
        </xs:element>
      </xs:schema>
      <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" 
    	xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
        <PersonTable xmlns="">
          <Person diffgr:id="Person1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
            <Name>Alice</Name>
            <Gender>Female</Gender>
          </Person>
          <Person diffgr:id="Person2" msdata:rowOrder="1" diffgr:hasChanges="inserted">
            <Name>Bob</Name>
            <Gender>Male</Gender>
          </Person>
          <Person diffgr:id="Person3" msdata:rowOrder="2" diffgr:hasChanges="inserted">
            <Name>Chris</Name>
            <Gender>Male</Gender>
          </Person>
        </PersonTable>
      </diffgr:diffgram>
    </DataSet>
    
    圖表2. 被格式化成XML的DataSet
    從上面的例子可以看出,直接使用DataSet作為返回類型,其結(jié)果是相當(dāng)復(fù)雜的,其中不但包含了DataSet中的數(shù)據(jù),還包括了數(shù)據(jù)更改的信息,以及DataSet的Schema。雖然有些工具能夠生成一個(gè)類似DataSet的客戶端類型,但無論是直接解析復(fù)雜的XML還是使用類似DataSet的類,都不夠直接不夠清晰。
    解決這個(gè)問題的方案有兩種:
    1) 用簡單數(shù)據(jù)類型構(gòu)造自定義類型,用每一個(gè)自定義類型對(duì)象封裝數(shù)據(jù)集中的一行,將自定義類型對(duì)象的數(shù)組(Array)返回客戶端;由于是用簡單數(shù)據(jù)類型定義,客戶端能夠完全不變的還原出自定義類型的定義;
    2) 用DataSet.WriteXML()方法將數(shù)據(jù)集中的數(shù)據(jù)提取成XML格式,并以字符串的形式返回給客戶端,再由客戶端解析XML字符串,還原出數(shù)據(jù)。由于使用WriteXML()的時(shí)候能夠過濾掉冗余信息,返回的內(nèi)容和圖表2中的內(nèi)容相比大大簡化了。
    下面就將用C#分別實(shí)現(xiàn)這兩種方案,并詳細(xì)演示如何在Java客戶端中調(diào)用并獲取數(shù)據(jù)。

    2. 創(chuàng)建.NET Web Services,返回?cái)?shù)據(jù)集合
    借助于Visual Studio.NET,只需編寫Web Method本身的代碼,即可非常快速的創(chuàng)建可以實(shí)用的Web Services:
    [WebMethod]
    public Person[] GetPersons()
    {
    	Person Alice=new Person("Alice","Female");
    	Person Bob=new Person("Bob","Male");
    	Person Chris=new Person("Chris","Female");
    	Person Dennis=new Person("Dennis","Male");
    
    	return new Person[]{Alice,Bob,Chris,Dennis};
    }
    
    [WebMethod]
    public string GetPersonTable()
    {
    	DataTable table=new DataTable("Person");		
    	table.Columns.Add("Name");
    	table.Columns.Add("Gender");
    	table.Rows.Add(new string[2]{"Alice","Female"});
    	table.Rows.Add(new string[2]{"Bob","Male"});
    	table.Rows.Add(new string[2]{"Chris","Female"});
    	table.Rows.Add(new string[2]{"Dennis","Male"});
    	table.Rows.Add(new string[2]{"Eric","Male"});
    	
    	DataSet dataset=new DataSet("PersonTable");
    	dataset.Tables.Add(table);
    	
    	System.Text.StringBuilder strbuilder=new System.Text.StringBuilder();
    	StringWriter writer=new StringWriter(strbuilder);
    	dataset.WriteXml(writer,System.Data.XmlWriteMode.IgnoreSchema);
    	
    	return strbuilder.ToString();
    }
    
    圖表3. 用.NET實(shí)現(xiàn)的XML Web Services
    在上面的代碼中,函數(shù)GetPersons()和GetPersonTable()分別對(duì)應(yīng)于"1. 概述"中所提到的兩種解決方案。其中,Person類型就是用于封裝數(shù)據(jù)集中一行數(shù)據(jù)的自定義的數(shù)據(jù)類型:
    [Serializable]
    public class Person
    {
    	public Person()
    	{
    	}
    
    	public Person(string name,string gender)
    	{
    		this.Name=name;
    		this.Gender=gender;
    	}
    
    	public string Name="";
    	public string Gender="";
    }
    
    圖表4. 自定義類型Person
    下面就是在Internet Exploerer里直接調(diào)用這兩個(gè)Web Method所得到的XML格式的結(jié)果:
    <?xml version="1.0" encoding="utf-8"?>
    <ArrayOfPerson xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://tempuri.org/">
      <Person>
        <Name>Alice</Name>
        <Gender>Female</Gender>
      </Person>
      <Person>
        <Name>Bob</Name>
        <Gender>Male</Gender>
      </Person>
      <Person>
        <Name>Chris</Name>
        <Gender>Female</Gender>
      </Person>
      <Person>
        <Name>Dennis</Name>
        <Gender>Male</Gender>
      </Person>
    </ArrayOfPerson>
    
    圖表5. GetPersons()的返回結(jié)果
    <PersonTable> <Person> 
    <Name>Alice</Name>
     <Gender>Female</Gender> 
    </Person> <Person>
     <Name>Bob</Name>
     <Gender>Male</Gender>
     </Person> <Person>
     <Name>Chris</Name>
     <Gender>Female</Gender>
     </Person> <Person>
     <Name>Dennis</Name> 
    <Gender>Male</Gender> 
    </Person> <Person>
     <Name>Eric</Name>
     <Gender>Male</Gender>
     </Person> </PersonTable>
    
    圖表6. GetPersonTable()的返回的String類型的值
    到這里,XML Web Service的創(chuàng)建就已經(jīng)完成了。.NET中創(chuàng)建的XML Web Services遵循的是統(tǒng)一的行業(yè)標(biāo)準(zhǔn)(SOAP、XML等),因此無論使用.NET語言還是使用非.NET語言,都可以調(diào)用它。尤其對(duì)于GetPersonTable()返回的結(jié)果來說,只要用XML Parser作簡單的處理,就能把數(shù)據(jù)提取出來。下面就將演示如何在Java中完成這一處理。

    3. 在Java中調(diào)用.NET Web Services,處理返回的數(shù)據(jù)集合
    編寫客戶端調(diào)用Web Services時(shí),最快速簡便做法的是利用工具根據(jù)Web Services的WSDL描述生成客戶端代理類(Proxy),而不是直接對(duì)SOAP Toolkit進(jìn)行編程。在.NET Framework中,這個(gè)工作可以由wsdl.exe完成。在Java中,可以在JBuilder或者VisualAge Java等Java IDE中安裝一個(gè)叫做WASP Developer的免費(fèi)插件,這個(gè)插件也能完成由WSDL描述生成Proxy類的工作。另外,該公司還提供了WASP Server for Java和WASP UDDI,降低了用戶用Java開發(fā)Web Services以及建立UDDI服務(wù)的難度。
    在本文的例子中,用了JBuilder 7+WASP Developer來調(diào)用前文中建立的.NET XML Web Services。在調(diào)用之前,首先是用WASP Developer生成Proxy類。從圖表7、8中可以看到,生成Proxy的工具已經(jīng)在Java中也創(chuàng)建了一個(gè)Person類:

    圖表7. 用WASP Developer生成的Proxy類
    package javaclient.service1Soap12Clientstruct;
    
    public class Person {
        public java.lang.String Name;
        public java.lang.String Gender;
    }
    
    /*
     * Generated by WSDLCompiler, (c) 2002, Systinet Corp.
     *                            http://www.systinet.com
     */
    
    圖表8. WASP Developer創(chuàng)建的Person類
    在Proxy類的基礎(chǔ)上,就可以訪問.NET編寫的Web Services并提取數(shù)據(jù)了。對(duì)于GetPersons()來說,由于已經(jīng)生成了Person類,所以調(diào)用代碼非常簡單直接:
    import org.idoox.webservice.client.WebServiceLookup;
    import org.idoox.wasp.Context;
    import javax.swing.*;
    import javax.swing.table.*;
    
    try{
      System.setProperty( "wasp.location","C:\\Home\\Util\\wasp_4.0SP2");
    
      javaclient.service1Soap12Client.Service1Soap service;
      String serviceURI = "http://localhost/dotNetHost/Service1.asmx";
      String wsdlURI = "http://localhost/dotNetHost/Service1.asmx?wsdl";
    
      WebServiceLookup lookup = (WebServiceLookup) Context.getInstance(Context.WEBSERVICE_LOOKUP);
      service = (javaclient.service1Soap12Client.Service1Soap) lookup.lookup(
                wsdlURI, 
                javaclient.service1Soap12Client.Service1Soap.class, 
                serviceURI);
    
      Person[] persons=
       service.GetPersons(new javaclient.service1Soap12Clientstruct.GetPersons()).GetPersonsResult;
      DefaultTableModel model=new DefaultTableModel(new String[]{"name","gender"},0);
      for(int i=0;i<persons.length;i++){
        model.addRow(new String[]{persons[i].Name.toString(),persons[i].Gender.toString()});
      }
      this.jTable1.setModel(model);
    }
    catch(Exception ex)
    {
      javax.swing.JOptionPane.showMessageDialog(this,ex.getMessage());
    }
    
    圖表9. 在Java中調(diào)用GetPersons()的代碼
    調(diào)用GetPersonTable()并解析XML字符串要相對(duì)復(fù)雜一些,需要用到XML Parser從圖表6中的XML字符串中提取數(shù)據(jù),并逐一顯示在JTable中。下面是從訪問Web Method到解析XML,最后提取數(shù)據(jù)并顯示的完整代碼,及其運(yùn)行結(jié)果截圖:
    import javax.swing.*;
    import javax.swing.table.*;
    
    import org.idoox.webservice.client.WebServiceLookup;
    import org.idoox.wasp.Context;
    
    import org.w3c.dom.*;
    import org.apache.xml.serialize.*;
    import org.apache.xerces.dom.*;
    
    try{
      System.setProperty( "wasp.location","C:\\Home\\Util\\wasp_4.0SP2");
    
      javaclient.service1Soap12Client.Service1Soap service;
      String serviceURI = "http://localhost/dotNetHost/Service1.asmx";
      String wsdlURI = "http://localhost/dotNetHost/Service1.asmx?wsdl";
    
      WebServiceLookup lookup = (WebServiceLookup) Context.getInstance(Context.WEBSERVICE_LOOKUP);
      service = (javaclient.service1Soap12Client.Service1Soap) lookup.lookup(
                wsdlURI, 
                javaclient.service1Soap12Client.Service1Soap.class, 
                serviceURI);
    
      String result=
       service.GetPersonTable(new javaclient.service1Soap12Clientstruct.GetPersonTable()).GetPersonTableResult;
      DefaultTableModel model=new DefaultTableModel(new String[]{"name","gender"},0);
    
      java.io.StringReader reader=new java.io.StringReader(result);
      org.apache.xerces.parsers.DOMParser parser=new org.apache.xerces.parsers.DOMParser();
      parser.parse(new org.xml.sax.InputSource(reader));
      org.w3c.dom.Document document=parser.getDocument();
      org.w3c.dom.NodeList children=document.getDocumentElement().getChildNodes();
    
      for(int i=0;i<children.getLength();i++){
        org.w3c.dom.Node node=children.item(i);
        if(node.getNodeName().equals("Person")){
          org.w3c.dom.NodeList personAttrNodes=node.getChildNodes();
          String name="N/A";
          String gender="N/A";
    
          for(int j=0;j<personAttrNodes.getLength();j++){
            org.w3c.dom.Node attrNode=personAttrNodes.item(j);
            String attrNodeName=attrNode.getNodeName();
            if(attrNodeName.equals("Name")){
              name=attrNode.getFirstChild().getNodeValue();
            }else if(attrNodeName.equals("Gender")){
              gender=attrNode.getFirstChild().getNodeValue();
            }else{
              continue;
            }
          }
          model.addRow(new String[]{name,gender});
        }
      }
      this.jTable1.setModel(model);
    }
    catch(Exception ex)
    {
      javax.swing.JOptionPane.showMessageDialog(this,ex.getMessage());
    }
    
    圖表10. 在Java中調(diào)用GetPersonTable()的代碼

    圖表11.調(diào)用GetPersonTable()的運(yùn)行結(jié)果

    4. 小結(jié)
    從前面的敘述和代碼中可以看出,對(duì)于"如何在Java/Delphi中使用.NET的Web Service返回的DataSet"的問題,雖然在非.NET語言環(huán)境中直接接受DataSet類型的返回值比較困難,但可以有其他的解決方案。
    對(duì)于第一種解決方案,也就是采用自定義數(shù)據(jù)類型,它的優(yōu)點(diǎn)是客戶端代碼非常簡單,容易編寫,而且容易理解。它的缺點(diǎn)是服務(wù)器端需要定義新的類,而且當(dāng)通過ADO.NET從數(shù)據(jù)庫中提取數(shù)據(jù)以后,還要再手工編寫代碼,將DataSet中的數(shù)據(jù)遍歷一遍,轉(zhuǎn)存成自定義類型的對(duì)象。
    對(duì)于第二種解決方案,就是用DataSet.WriteXML()的方案,它的優(yōu)點(diǎn)和缺點(diǎn)正好和第一種方案是互補(bǔ)的。它在客戶端需要編寫較多的代碼,尤其是需要用XML Parser編程,提高了編程的難度。另一方面,它在服務(wù)器端比較簡單。如果開發(fā)者在原先的純.NET環(huán)境(即客戶端也是.NET)中已經(jīng)開發(fā)了返回類型為DataSet的Web Services,那么當(dāng)開發(fā)者希望在客戶端引入非.NET語言時(shí),服務(wù)器端只需要簡單的再增加一個(gè)Web Method,通過簡單的WriteXML()調(diào)用對(duì)原有的方法進(jìn)行簡單的包裝,就能夠適用于非.NET客戶端了。
    從更廣闊的角度來看,上面兩種解決方案也可以用在"非.NET服務(wù)器+.NET客戶端"的Web Services環(huán)境中。在各種非原生(Native)的情況下,盡量使用簡單數(shù)據(jù)類型,或者使用XML來表達(dá)數(shù)據(jù),總是上佳的選擇。
    posted on 2005-04-25 12:14 小魚兒 閱讀(324) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产亚洲情侣一区二区无| 永久免费av无码网站大全| 国产亚洲AV夜间福利香蕉149| 亚洲色在线无码国产精品不卡 | 亚洲美女精品视频| 久久国产乱子精品免费女| 亚洲精品无码国产| 免费观看一区二区三区| 亚洲AV无码国产精品麻豆天美 | 久久精品无码专区免费东京热| 国产日韩亚洲大尺度高清| 香蕉免费一级视频在线观看| 浮力影院亚洲国产第一页| 国产日韩在线视频免费播放| 国产亚洲成av人片在线观看| 精品国产免费一区二区三区香蕉 | 巨波霸乳在线永久免费视频| 亚洲视频一区在线| 免费福利网站在线观看| 亚洲国产精品ⅴa在线观看| 麻豆国产入口在线观看免费 | 久久夜色精品国产亚洲av| 国产精品免费大片一区二区| 亚洲精品成人片在线播放| 99久久免费观看| 日韩亚洲不卡在线视频中文字幕在线观看 | 亚洲精品9999久久久久无码 | 国产精品成人免费观看| 久久久久亚洲AV片无码| 18女人毛片水真多免费| 亚洲中文字幕乱码AV波多JI| 四虎影在线永久免费观看| a级成人毛片免费图片| 亚洲国产精品线观看不卡| 国产免费爽爽视频免费可以看| 国产亚洲精品国产福利在线观看 | 一个人看的免费高清视频日本| 亚洲女初尝黑人巨高清| 免费黄色福利视频| 日本精品久久久久久久久免费| 亚洲日本一区二区三区|