-------------------------------------------------------------------
目录
1. 概述
2. 创建.NET Web Services,返回数据集合
3. 在Java中调用.NET Web Services,处理返回的数据集合
4. 小结
-------------------------------------------------------------------
1.概述
很多正在开发或者打算开发XML Web Services的程序员都问过这样的一个问题:"我的Web Service返回的结果是一个DataSet类型的对象,但如果我的客户端不是用.NET写的(因而没有内建的DataSet类型),那该如何调用这个Web Service并访问DataSet中的数据呢?"。
对于这个问题,首先应该说的是:1)在多种语言共存的编程环境下,是不适合使用类似DataSet这种只属于特定语言的数据类型的。不管是在XML Web Services还是CORBA的环境中,都应该尽量使用简单数据类型以及简单数据类型的数组。2)应当很谨慎的决定是否需要通过
Web Service来返回大量数据。由于网络传输的开销既包括HTTP连接建立的时间,也包括传送数据的时间,因此需要在减少访问服务器次数和减少网络传输量之间寻找一个合适的平衡。如非必须,则不适合通过Web Service传送含有几十条或者几百条数据的数据表。
然后,就问题本身而言,.NET Web Services返回的DataSet类型是可以直接被其他非.NET的客户端解析的,因为即便是DataSet类型的返回值,也会被表达成XML格式再进行传输。下面的例子就是一个返回类型为DataSet的Web Method,及其被调用后返回的XML格式数据:
[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作为返回类型,其结果是相当复杂的,其中不但包含了DataSet中的数据,还包括了数据更改的信息,以及DataSet的Schema。虽然有些工具能够生成一个类似DataSet的客户端类型,但无论是直接解析复杂的XML还是使用类似DataSet的类,都不够直接不够清晰。
解决这个问题的方案有两种:
1) 用简单数据类型构造自定义类型,用每一个自定义类型对象封装数据集中的一行,将自定义类型对象的数组(Array)返回客户端;由于是用简单数据类型定义,客户端能够完全不变的还原出自定义类型的定义;
2) 用DataSet.WriteXML()方法将数据集中的数据提取成XML格式,并以字符串的形式返回给客户端,再由客户端解析XML字符串,还原出数据。由于使用WriteXML()的时候能够过滤掉冗余信息,返回的内容和图表2中的内容相比大大简化了。
下面就将用C#分别实现这两种方案,并详细演示如何在Java客户端中调用并获取数据。
-------------------------------------------------------------------
2. 创建.NET Web Services,返回数据集合
借助于Visual Studio.NET,只需编写Web Method本身的代码,即可非常快速的创建可以实用的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实现的XML Web Services
在上面的代码中,函数GetPersons()和GetPersonTable()分别对应于"1. 概述"中所提到的两种解决方案。其中,Person类型就是用于封装数据集中一行数据的自定义的数据类型:
[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里直接调用这两个Web Method所得到的XML格式的结果:
<?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()的返回结果
<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的创建就已经完成了。.NET中创建的XML Web Services遵循的是统一的行业标准(SOAP、XML等),因此无论使用.NET语言还是使用非.NET语言,都可以调用它。尤其对于GetPersonTable()返回的结果来说,只要用XML Parser作简单的处理,就能把数据提取出来。下面就将演示如何在Java中完成这一处理。
-------------------------------------------------------------------
3. 在Java中调用.NET Web Services,处理返回的数据集合
编写客户端调用Web Services时,最快速简便做法的是利用工具根据Web Services的WSDL描述生成客户端代理类(Proxy),而不是直接对SOAP Toolkit进行编程。在.NET Framework中,这个工作可以由wsdl.exe完成。在Java中,可以在JBuilder或者VisualAge Java等Java IDE中安装一个叫做WASP Developer的免费插件,这个插件也能完成由WSDL描述生成Proxy类的工作。另外,该公司还提供了WASP Server for Java和WASP UDDI,降低了用户用Java开发Web Services以及建立UDDI服务的难度。
在本文的例子中,用了JBuilder 7+WASP Developer来调用前文中建立的.NET XML Web Services。在调用之前,首先是用WASP Developer生成Proxy类。从图表7、8中可以看到,生成Proxy的工具已经在Java中也创建了一个Person类:
图表7. 用WASP Developer生成的Proxy类
package javaclient.service1Soap12Clientstruct;
public class Person {
public java.lang.String Name;
public java.lang.String Gender;
}
图表8. WASP Developer创建的Person类
在Proxy类的基础上,就可以访问.NET编写的Web Services并提取数据了。对于GetPersons()来说,由于已经生成了Person类,所以调用代码非常简单直接:
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");
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中调用GetPersons()的代码
调用GetPersonTable()并解析XML字符串要相对复杂一些,需要用到XML Parser从图表6中的XML字符串中提取数据,并逐一显示在JTable中。下面是从访问Web Method到解析XML,最后提取数据并显示的完整代码,及其运行结果截图:
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");
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中调用GetPersonTable()的代码
图表11.调用GetPersonTable()的运行结果
-------------------------------------------------------------------
4. 小结
从前面的叙述和代码中可以看出,对于"如何在Java/Delphi中使用.NET的Web Service返回的DataSet"的问题,虽然在非.NET语言环境中直接接受DataSet类型的返回值比较困难,但可以有其他的解决方案。
对于第一种解决方案,也就是采用自定义数据类型,它的优点是客户端代码非常简单,容易编写,而且容易理解。它的缺点是服务器端需要定义新的类,而且当通过ADO.NET从数据库中提取数据以后,还要再手工编写代码,将DataSet中的数据遍历一遍,转存成自定义类型的对象。
对于第二种解决方案,就是用DataSet.WriteXML()的方案,它的优点和缺点正好和第一种方案是互补的。它在客户端需要编写较多的代码,尤其是需要用XML Parser编程,提高了编程的难度。另一方面,它在服务器端比较简单。如果开发者在原先的纯.NET环境(即客户端也是.NET)中已经开发了返回类型为DataSet的Web Services,那么当开发者希望在客户端引入非.NET语言时,服务器端只需要简单的再增加一个Web Method,通过简单的WriteXML()调用对原有的方法进行简单的包装,就能够适用于非.NET客户端了。
从更广阔的角度来看,上面两种解决方案也可以用在"非.NET服务器+.NET客户端"的Web Services环境中。在各种非原生(Native)的情况下,尽量使用简单数据类型,或者使用XML来表达数据,总是上佳的选择。
相关推荐
在ASP.NET中,获取SharePoint列表数据可以通过多种方式实现,这里主要介绍了两种方法:一种是使用`SPSite`和`SPWeb`对象直接访问SharePoint站点的内部API(DLL方式),另一种是通过调用SharePoint的Web Services接口...
### 如何向WebServices中传送多个自定义类对象 在.NET框架中,Web Services是一种用于在不同应用程序之间进行通信的服务接口。它通过HTTP协议来发送和接收XML格式的数据。本篇将详细介绍如何在一个Web Service中...
它基于一组标准和规范,支持XML数据交换,通过Web Services实现了跨平台的远程调用。.NET Framework 包括两个主要组成部分:公共语言运行库(Common Language Runtime, CLR)和一套统一的类库。 - CLR 提供了一个...
【C#.NET范例3】是一个集合,包含了关于C#.NET编程中的网络和Web Service相关的实例源代码。这个资源旨在帮助开发者深入理解如何在C#.NET环境下进行网络通信和构建Web Service应用程序。以下是对这两个主要知识点的...
本文旨在探讨这两个平台在Web Services支持方面的主要特点,并对比它们在技术、市场接受度以及第三方支持等方面的差异。 #### 技术背景介绍 - **J2EE** 是由Sun Microsystems提出的一套企业级Java标准集合,旨在为...
1. **LINQ**: LINQ允许开发者使用类似SQL的查询语法在.NET语言中操作数据,包括数据库、XML文档和集合。在源码中,我们可以期待看到如何使用LINQ to SQL或Entity Framework进行数据库交互的示例。 2. **AJAX** ...
- **Web Services**:基于XML和SOAP标准,用于构建跨平台的分布式应用,通常用于不同系统之间的数据交换和服务调用。 9. **实例化与构造函数** - **构造函数**:用于初始化新创建的对象,可以重载以支持不同的...
- `Object.ReferenceEquals`方法用于比较两个对象是否引用同一个对象。 - 对于基本类型(如int),它们的值相等并不意味着引用相等。 #### 10. SQL注入的防范措施 - **知识点**: - SQL注入是一种常见的安全漏洞...
数据示例目录中包含了多个示例项目,每个项目都展示了如何使用 VB.NET 语言来操作数据库和数据表。这些示例包括: * CreateDB:演示如何从代码中执行 SQL 语句以创建数据库、表、存储过程和视图 * ...
- .NET 提供了方便的方法来处理 XML 命名空间。 #### 15. WSDL 与 UDDI **知识点:** - **WSDL (Web Services Description Language)**: - 一种 XML 格式的语言,用于描述 Web 服务。 - 定义了服务的操作、消息...
- **WSDL (Web Services Description Language)**:是一种XML格式的语言,用于描述Web服务的功能、接口以及消息交换模式。 #### 16. SOAP协议介绍 - **SOAP (Simple Object Access Protocol)**:是一种轻量级协议...
5. **调用Web服务**: 在VB.NET中,我们可以使用.NET框架提供的`System.Web.Services`命名空间下的`WebReference`或`ServiceReference`来添加对Web服务的引用。一旦添加,就可以像调用本地方法一样调用Web服务的函数...
.NET框架提供了ASP.NET Web Services(ASMX)和WCF(Windows Communication Foundation)两种技术来创建Web服务。 **C# Web Service的创建与调用:** 1. **ASMX Web Service**:这是一种早期的Web服务实现方式,...
8. **LINQ**:语言集成查询,是.NET Framework的一部分,提供了一种统一的查询语言,可在XML、数据库、集合等多种数据源上执行查询,简化了数据操作。 9. **WCF(Windows Communication Foundation)**:WCF是一个...
.NET Framework框架具有两个主要组件: * 公共语言运行时(CLR)是.NET框架的基础 * 框架类库是一个综合性的面向对象的可重用类型集合,利用它可以开发包括传统命令行或者WinForms应用程序,以及ASP.NET所提供的...
11.3 静态和非静态的方法.129 11.4 方法的重载.130 11.5 操作符重载.134 11.6 小 结.137 第十二章 域 和 属 性 .139 12.1 域 .139 12.2 属 性 .143 12.3 小 结 .146 第十三章 事件和索引指示器 .148 ...
28.SQLSERVER服务器中,给定表 table1 中有两个字段 ID、LastUpdateDate,ID表示更新的事务号, LastUpdateDate表示更新时的服务器时间,请使用一句SQL语句获得最后更新的事务号 答:Select ID FROM table1 Where ...
WSDL(Web Services Description Language)是一种用于描述Web服务的XML格式,它定义了服务的操作、消息格式、数据类型和网络地址等信息。SOAP(Simple Object Access Protocol)是一种用于在Web服务之间交换结构化...