数据绑定实用入门
Brett McLaughlin (brett@oreilly.com), 编辑, O'Reilly and Associates
Brett McLaughlin 从 Logo 时代(还记得那个小三角吗?)就开始从事计算机。他目前专门使用 Java 相关技术构建应用程序基础设施。他最近几年为 Nextel Communications 和 Allegiance Telecom, Inc. 实现了这些基础设施。Brett 是 Java Apache 项目 Turbine 的缔造者之一,该项目使用 Java servlet 为 Web 应用程序开发建立了可重用的组件体系结构。他还参与了 EJBoss 项目(一种开放源代码的 EJB 应用程序服务器)和 Cocoon(一种开放源代码的 XML Web 发布引擎)。
简介: 数据绑定在今天的 Java 技术和 XML 编程世界中虽然是老生常谈,但仍然有很大的误解。这个专栏抛开所有空洞的理论,把重点放在应用数据绑定需要了解的概念上。您将了解一般数据绑定和 XML 世界中的数据绑定之间的区别,以及往返、语义等价和对数据绑定软件包的要求。
标记本文!
发布日期: 2004 年 5 月 01 日
级别: 初级
访问情况 377 次浏览
建议: 0 (添加评论)
平均分 (共 1 个评分 )
既然阅读本专栏,就说明您至少对 XML 数据绑定有一定的兴趣。若是在一年前,我就不得不定义数据绑定是什么,深入到复杂的概念,这是一项令人厌倦的工作,通常要花费几页的篇幅。不过现在是 2004 年,而不是一年以前了,基本上所有目前从事 XML 和 Java 开发的人员的思想中,数据绑定似乎已经扎下了根。由于某些原因,坦白地讲,这令我感到困惑,甚至连 SAX 和 DOM 代表什么也不知道的 XML 新手都在天天使用数据绑定。因此对于您(单击这篇文章标题的人)的背景知识,我并不像在过去所能做到的那样肯定。
不过这并不一定是件坏事。关于数据绑定的丰富信息以及这些信息对程序员的影响,意味着您很快就可以找到一些非常好的资料,不必花费一星期一星期的时间纠缠在细小的概念细节上,这对您支付帐单没有帮助(还令您昏昏欲睡)。我还是要谈一点基本概念,不过不用担心,我尽量让概念的介绍不那么痛苦。
又一篇入门文章?真是如此吗?
既然每个人都熟悉数据绑定,何必再为什么定义和概念烦扰呢?为何不直接开始编码呢?当然,这听起来很吸引人(我向您保证,这种想法也同样令我着迷)。但是,人们认为自己了解某事并不意味着真的如此。换句话说,虽然很多人每天把“数据绑定”挂在嘴上,但很少有人真正理解这个词的含义,能够 把握可靠数据绑定软件包所涉及问题的人就更少了。为了保证每个人都有一致的基础,首篇文章将详细介绍一些重要的概念,这些概念您可能从未听说,或者只在某个含含糊糊的网页上见到过。重点放在这些术语的实际应用上,然后在下一篇文章中深入剖析更多的代码。因此坚持下去吧--不用很长时间,也不很难。
一般的数据绑定
首先,必须暂时放一放 XML 数据绑定(得承认,您满脑子想的都是这个),来看看更一般意义上的数据绑定。虽然多数程序员都认为数据绑定就是 XML 文档和某种 Java 编程结构之间的转换过程,但这仅仅是数据绑定技术的一种具体应用。在展开这个复杂的问题之前,最好先看一看更广阔的背景。
传统的数据绑定
简单地讲, 数据绑定是指取出一些数据(比如从 XML 文档、文本文件或者数据库中)并通过程序表示这些数据的过程--把数据 绑定到虚拟机(VM)能够理解并且可以操作的某种内存中结构。相应地,数据绑定软件包应该能够用 VM 上修改的数据更新底层存储媒介(XML 文档、文件或数据库分区)中的数据。如果连这些 最少的功能都不能实现,就称不上数据绑定软件包--至少从这个词的传统意义上讲不是的。
当然这些都非常麻烦,因此更常见的是针对一种格式媒介和一种编程语言的数据绑定程序包。
把数据绑定扩展到 Java 技术
既然大家都是很棒的 Java 程序员,我就把目光集中到 Java 编程语言上。当然过程性语言也能执行数据绑定任务,但使用面向对象语言在内存中表示数据更简单,特别是如果数据带有某种结构比如数据库或 XML 文档中的数据。Java 语言已经证明非常适合这项任务,这可能正是和其他语言相比 Java 数据绑定软件包引起更多关注(至少就我看到的而言)的原因。
既然编程语言限制为 Java,也可以限制数据绑定管道的另一端,数据格式媒介。首先看一种非常简单的情况,文本文件。数据绑定的圈子中很少提到文本文件,大概是因为 Java 语言--尤其是 Jakarta Commons 软件包(请参阅 参考资料)--提供了丰富的字符串解析工具,数据绑定在这里有点大材小用。
另外一种常见的数据格式媒介是数据库。从本文的主旨出发,我把关系数据库(RDBMS)和面向对象数据库(OODBS)放在一起,不单独讨论。在这种情况下使用数据绑定,程序员就不需要使用传统的数据库 API,比如 JDBC 或者 Enterprise JavaBeans(EJB)。相反,数据库操纵是在幕后进行的,这是数据绑定 API 的工作。就此您可能已经看出这些讨论的重要性,它表明,数据绑定的一个优点是能够向程序员屏蔽更加复杂的 API。编写像清单 1 那样的代码,显然要比直接使用 JDBC 容易得多。
清单 1. 使用数据绑定 API 访问数据库
// Get an instance of a data binding factory
Factory factory = DBFactory.newInstance();
factory.connect();
List employees = factory.unmarshal(DatabaseConstants.EMPLOYEE_TABLE);
// Manipulate data in employee objects
for (Iterator i = employees.iterator; i.hasNext(); ) {
Employee employee = (Employee)i.next();
System.out.println("First name: " + employee.getFirstName());
System.out.println("Last name: " + employee.getLastName());
// etc...
}
比数据库更常见的是将此类 API 用于 XML,从 XML 文档中提取数据。这就是问题的由来:程序员如此关注 XML上的数据绑定而非一般意义上的数据绑定,以至于常常把通用 API 看作是针对特定格式的。比如,清单 2 中的代码和 清单 1是等价的,最近我发现很多咨询建议中使用这类代码。
清单 2. 使用数据绑定 API 访问 XML 文档
// Get an instance of a data binding factory
Factory factory = XMLFactory.newInstance();
factory.connect();
List employees = factory.unmarshal(XMLConstants.EMPLOYEE_DOCUMENT);
// Manipulate data in employee objects
for (Iterator i = employees.iterator; i.hasNext(); ) {
Employee employee = (Employee)i.next();
System.out.println("First name: " + employee.getFirstName());
System.out.println("Last name: " + employee.getLastName());
System.out.println("Address (line 1): " +
employee.getAttribute("street1"));
System.out.println("Address (line 2): " +
employee.getAttribute("street2"));
}
特别要注意粗体显示的两行--这里把 XML 语义引入到了实际的数据绑定应用中。这种做法非常糟糕,会令您急得手忙脚乱。在使用(和选择)数据绑定 API 时,应该寻找 通用的API,而不是 专用的API。这就是为何我要花费您这么多宝贵的时间,介绍各种数据绑定 API 的互换性,来说明所谓的具体细节实际上是实现的细节,而不是 API 的细节 。如果在代码中暴露 XML 语义和数据库语义,就可能得到编写很差、实现很差或者两者都很差的数据绑定 API。从一种存储媒介改为另一种存储媒介应该很简单,对代码的影响很小。不要再做 Java 和 XML 数据绑定程序员了,开始转变为 数据绑定程序员吧。您会发现您的代码和所实现的功能比过去更加健壮,更加灵活。
虽然 API 是专用的,但仍然要使用
一些人可能在这里已经看到了一线曙光,但是仍然要使用特定的数据绑定 API 或实现。您可能使用类似 清单 2的代码,或者其他类似的东西,在不需要的的地方公开数据格式结构。那么好吧--实际上可以通过少量的工作来获得前述的效果。这时应考虑编写一个 包装程序 API。包装程序 API 位于开发人员和数据绑定 API(它大概不能很好地完成自己的工作)之间。您可以包装有问题的功能,比如 getAttribute() 或 getChild() 调用(这是 XML 专用的),编写新的类调用这些方法,并使用更加有意义而且存储中立的方法名。还应该考虑准备一个工厂类,以便很容易从 XML 媒介转到数据库媒介(或者有一天可能会用到的其他媒介)。这不是一项轻松的任务,但有一定经验的开发人员仍然可以完成。我将在这里说明如何创建包装程序 API,但是我计划在本专栏以后的文章中还会讨论这个话题。
理解了通用数据绑定 API 的用处以后,您可能已经准备学习如何正确地选择和使用数据绑定 API。在这篇入门介绍的最后,我们将学习一些您可能还不熟悉的定义。这些概念对于保证 API 的正确运行(尤其是在处理 XML 时)至关重要;了解这些定义还可以避免造成 API 输出的 XML 和输入不相符。
编组和解组
首先,只要您稍微用过一点数据绑定,对这两个术语应该很熟悉。先回顾一下这两个术语,然后我们将讨论一些更有趣的术语。
编组(Marshalling)是把内存中的数据转化到存储媒介上的过程。因此在 Java 和 XML 环境中,编组就是把一些 Java 对象转化成一个(或多个) XML 文档。在数据库环境中,则是把 Java 表示的数据存入数据库。显然,编组的秘密在于把 Java 实例中的面向对象结构转化成适用于 XML 的 扁平结构,或者 RDBMS 中的关系结构(使用 Java 技术转换到 OODBMS 实际上很简单)。
解组(Unmarshalling)是把数据从存储媒介转换到内存中的过程--正好与编组相反。因此需要把 XML 文档解组到 Java VM 中。这里的复杂性不是在扁平数据中,因为这不是必需的,而在于从正确的数据到正确的 Java 代码变量的映射。如果映射是错误的,就不可能正确地访问数据。当然,如果再尝试重新编组还会造成更大的问题,并且问题传播得很快。
往返
往返(Round-tripping)可能是最重要也最容易误解的数据绑定术语。往返用于描述从存储媒介到内存然后回到存储媒介的完整循环。在 XML 和 Java 技术环境中,这就意味着从 XML 文档到 Java 实例变量,然后再回到 XML 文档。正确的往返要求,如果中间没有修改数据,XML 输入和 XML 输出应该是等同的。换句话说,清单 3 中的文档 input.xml 和 output.xml 应该基本上相同。
清单 3. 往返
// Get an instance of a data binding factory
Factory factory = XMLFactory.newInstance();
factory.connect();
List employees = factory.unmarshal("input.xml");
employees.marshal("output.xml");
如果输入和输出不能正确地匹配,就说明往返中存在问题,实际应用这种 API 很快就会陷入困境。如果把数据传入 VM 内存时不能依靠 API 正确地保持数据,您基本上就陷入了绝境。下一篇文章中将分析 Sun JAXB API 的往返能力,看看是否能实现期望的功能。
语义等价
因为 XML 是数据的文本格式,它有一些有趣的怪癖。比方说,XML 处理(和忽略)空白的方式不是由自身决定的。是否存在 DTD 或者模式影响到空白的处理; CDATA 元素的使用影响实体处理;一个编辑器中的缩进编排格式到另一个编辑器中可能会成为一团乱麻。
这些还不够,XML 对数据及其顺序有非常特殊的规则。在 XML 文档中,元素属性的顺序 不重要。因为这种无序性和空白处理的不同,两个看起来有天壤之别的文档可能实际上包含完全相同的数据。在这种情况下,说两个文档“相同”或者“相等”实际上是不严格的。这就引入了另一个术语: 语义等价。就是说,从文档中所含数据和涉及的结构的角度来看,两个文档是相同。尽管文档看起来可能彼此不同,但从数据的角度看是等价的。比如,看看清单 4 中的代码段。
清单 4. 简单的格式化的 XML 文档
<employees>
<employee id="1045" ssn="498123049" firstName="Bob" lastName="Smith">
<address>
<street>109 Fairfield</street>
<city>Mesquite</city>
<state country="US" code="TX" />
<zipCode>75150</zipCode>
</address>
</employee>
</employees>
这是一个简单的、格式良好的 XML 文档,很容易阅读和理解。但是看一看清单 5,仔细读起来就不那么舒服。
清单 5. 不那么好的 XML 文档
<employees><employee firstName="Bob" ssn="498123049" lastName="Smith" id="1045" >
<address> <street>109 Fairfield</street>
<city>Mesquite</city> <state code="TX" countryCode="US"></state>
<zipCode>75150</zipCode></address>
</employee> </employees>
您可能已经看到,这两个清单包含着同样的数据,事实上它们在语义上是等价的。因为这个例子很简单,所以等价性不难确定。但是,如果 XML 文档有成百上千条记录,每个元素都有多个属性(都能以任意的顺序出现),就很难判定语义上的等价性。这也是数据绑定框架中最困难的部分--想想上一节所述的往返。正确的往返不要求输入和输出文档看起来一致,只要求它们在语义上是等价的。因此现在要指出的是,如果说 API 能正确地往返,这就要求您了解 XML 的基础,并且保证您的 API 完全遵循这些规则。
虽然一些 API 提供了各种各样的机制定制输出,但为了保证语义等价,不 一定要使用这种选项。和往返一样,我也准备在下一篇文章中分析 JAXB 的语义等价处理,看看输入和输出文档在结构上的区别。我还将考察文档在解组和编组过程中发生的任何变化。
结束语
可能读完了本文后,有些读者感到它没有讲 如何做什么事情。但是,我认为如果花点时间掌握了数据绑定的基础,特别是往返和语义等价,您会发现在使用数据绑定 API 时,您可以编写出更好的、最终也更快的程序。这也是深入学习下一篇文章--JAXB API 的基础。同时,您也可以使用喜欢的 API 作一些简单的测试,看看它是否(理想地)保持了语义等价性。好了,下一篇文章再见。
分享到:
相关推荐
WPF的数据绑定功能非常强大,在控件中使用数据绑定功能会为你节省大量的处理时间。本示例中,将一个变量绑定到一个控件上,在代码中改变变量值,并立刻引起控件值的变化。此代码经过删减,仅仅保留精简内容,一看就...
.NET数据绑定是微软开发平台中的一个核心特性,主要用于在应用程序的UI层与数据源之间建立动态的连接,使得数据能够实时地反映到用户界面中。在ASP.NET中,数据绑定尤其重要,它使得Web应用程序能够轻松地显示和操作...
《WINDOWS FORMS 2.0数据绑定--.NET智能客户端数据应用程序设计》是关于.NET Framework 2.0时代Windows Forms应用程序开发的重要参考资料,特别聚焦于数据绑定这一核心特性。数据绑定是.NET框架中的一个强大功能,它...
在C#编程中,数据绑定是一项关键特性,它允许开发者将UI控件与数据源连接起来,实现数据的动态展示和交互。数据绑定控件在Windows Forms和WPF(Windows Presentation Foundation)等平台上广泛使用,简化了用户界面...
10. 动态数据绑定:在某些情况下,你可能需要动态地创建控件并绑定数据,这可以通过在运行时创建控件并设置其数据绑定属性来实现。 总之,VB.NET的数据绑定机制提供了丰富的功能,使得开发者能够方便地将数据展示在...
在Windows Presentation Foundation (WPF) 中,数据绑定是将用户界面(UI...同时,WPF的数据绑定还支持转换器、验证规则等功能,进一步增强了其灵活性和实用性。学习和掌握这些绑定方式是每个WPF开发者必备的基础技能。
本文将深入探讨如何实现DevExpress TreeList的数据绑定,以及KeyFieldName和ParentFieldName属性的重要性。 一、数据绑定基础 在DevExpress TreeList中,数据绑定是指将数据源(如数据库表、对象集合或XML文件)与...
- **双向数据绑定:** 实现控件与数据模型之间的双向通信,即用户更改控件值时会自动更新数据模型,反之亦然。 #### 框架层数据绑定的优点 - **可重用性和维护性:** - **分离数据与视图:** 数据绑定机制允许...
2. C#代码中的数据绑定:在代码后面,可以通过`Binding`类创建数据绑定实例,并将其设置给控件的`DataContext`属性或特定的`Binding`属性。 3. MVVM(Model-View-ViewModel)模式:这是一种流行的设计模式,鼓励...
C#数据绑定是.NET框架中一个关键的概念,它在Windows Forms、WPF(Windows Presentation Foundation)和ASP.NET等环境中广泛使用。数据绑定允许UI(用户界面)组件与数据源进行同步,使得数据的变化能够实时反映在...
在C#代码后端,我们可以通过以下方式实现数据绑定: ```csharp GridView1.DataSource = GetData(); GridView1.DataBind(); ``` 其中`GetData()`方法返回你要绑定的数据源。 6. 自定义列和模板字段: ...
2. 双向数据绑定:双向数据绑定允许数据在模型和视图之间自由流动。当视图中的组件(如文本框)的值改变时,模型也会同步更新,反之亦然。 数据绑定的工作原理: 在FLEX中,数据绑定使用Observer模式实现。每个绑定...
在Visual Studio 2005 (VS2005) 中,数据绑定是连接应用程序界面与数据库记录的关键技术,使得开发者能够轻松地显示、编辑和管理数据库中的信息。本教程将详细阐述如何利用数据绑定来浏览数据库记录。 一、安装与...
数据绑定是软件开发中的一个重要概念,特别是在用户界面(UI)设计中。在Windows Phone平台上,数据绑定是构建动态、响应式应用程序的关键技术。本教程将深入探讨如何在Windows Phone应用中实现简单数据绑定。 首先,...
在实际应用中,例如使用Access 2000数据库,可以通过以下代码进行数据绑定: ```csharp string strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb"; OleDbConnection myConn = new OleDbConnection...
数据绑定是Windows Presentation Foundation(WPF)框架中的核心特性,它简化了用户界面(UI)与应用程序业务逻辑之间的数据交互。在WPF中,数据绑定允许开发者将UI元素的属性与数据源的属性关联起来,确保UI的更新...
**WPF UI数据绑定** Windows Presentation Foundation (WPF) 是微软.NET Framework的一部分,它提供了一种强大的用户界面(UI)开发框架。其中,数据绑定是WPF中的核心特性,允许UI元素与应用程序中的数据源进行...
在Windows Presentation Foundation(WPF)中,数据绑定是一种强大的机制,它允许UI元素与应用程序的数据模型之间进行自动同步。这个“WPF简单数据绑定demo”是专为新手设计的,旨在帮助初学者快速掌握这一核心概念...
微信小程序学习demo:从服务器获取数据,并且数据绑定组件(源代码+截图)微信小程序学习demo:从服务器获取数据,并且数据绑定组件(源代码+截图)微信小程序学习demo:从服务器获取数据,并且数据绑定组件(源代码+截图...