中甲

Java SE6新特性- XML API 与Web服务

2019-09-13 19:30:12来源:励志吧0次阅读

文章主要介绍 Java SE 6 在 API 库方面的部分新特性,通过一些例子和讲解,帮助开发者在编程实践当中更好的运用 Java SE 6,提高开发效率。本文是系列文章的最后一篇,主要介绍了 Java SE 6 中提供的 XML 处理框架,以及在此框架之上结合注释(Annotation) 技术,所提供的强大的针对 Web 服务的支持。  Java SE 6 做为一个开发平台,针对不同的应用开发需求,提供了各种各样的技术框架。XML 处理框架是 JDK 6 的重要组成部分之一。它为应用程序开发人员提供了一个统一的 XML 处理 API。这种框架结构有两个作用:一方面,开发人员透过这些框架,可以透明的替换不同厂商提供的 XML 处理服务;另一方面,服务提供商可以透过这些框架,将自己的产品插入到 JDK 中。这种框架一般被称为 Service Provider 机制。Java SE 6 的 XML 处理功能分为两个部分:XML 处理(JAXP)和 XML 绑定(JAXB)。在 XML 处理框架之上,Java SE 6 结合了注释(Annotation)技术,提供了强大的针对 Web 服务的支持。

本文首先介绍 Service Provider 机制及其在 XML 框架中的应用。然后介绍 Java SE 6 中 XML 框架的功能,包括 SAX,StAX,DOM 三种机制。最后介绍在此基础之上构建 Web 服务的技术。JAXB 和 Web 服务的开发关系紧密,故 JAXB 的介绍也放在 Web 服务部分介绍。本文内容基于 Java SE 6 SDK。

Service Provider 机制

对于同一个功能,不同的厂家会提供不同的产品,比如不同品牌的轮胎、插头等。在软件行业,情况也是如此。比如,对于数据的加密解密,不同的厂家使用不同的算法,提供强度各异的不同软件包。应用软件根据不同的开发需求,往往需要使用不同的软件包。每次更换不同的软件包,都会重复以下过程:更改应用软件代码 -> 重新编译 -> 测试 -> 部署。这种做法一般被称为开发时绑定。这其实是一种比较原始的做法,缺乏灵活性和开放性。于是应用运行时绑定服务提供者的做法流行开来。具体做法是,使用配置文件指定,然后在运行时载入具体实现。Java SE 平台提供的 Service Provider 机制是折衷了开发时绑定和运行时绑定两种方式,很好的满足了高效和开放两个要求。

构成一个 Service Provider 框架需要大致三个部分,图 1 给出了一个典型的 Service Provider 组件结构。Java SE 平台的大部分 Service Provider 框架都提供了 3 个主要个组件:面向开发者的 Application 接口,面向服务提供商的 Service Provider 接口和真正的服务提供者。

图 1. Service Provider 的组件结构

这样做的主要好处包括:

提供了供应商的中立性,应用代码与服务提供商完全独立,互不依赖。应用程序开发者针对 图 1 中 Application 接口进行开发。这个接口将不同提供商的接口差异性屏蔽掉了。无论使用哪个厂商的服务,应用程序都是针对一个稳定、统一的接口开发,业务逻辑和第三方组件之间有很强的独立性。如果有需要,应用程序可以针对不同提供商重新部署。清单 1 显示某应用程序中的一段代码。

清单 1. 通过统一应用程序接口获得服务

SAXParserFactory factory = SAXParserFactory.newInstance();

System.out.println(factory.getClass());

// Parse the input

SAXParser saxParser = factory.newSAXParser();

System.out.println(saxParser.getClass());

Output: class org.apache.xerces.jaxp.SAXParserFactoryImpl

Output: class org.apache.xerces.jaxp.SAXParserImpl

本例中 saxParser 的类型被声明为 SAXParser,但实际类型如 清单 1 中显示,为 org.apache.xerces.jaxp.SAXParserImpl。实际类型是由 SAXParserFactory 的静态方法 newInstance 查找配置文件,并实例化得到的。图 2 展示了 Java SE 6 中 XML 包的 Service Provider 的交互细节。请参考 Apache Harmony 项目的具体代码(参见 参考资源)。

图 2. XML 包的 Service Provider 结构

提供了扩展性,更多的服务可以加入开发平台;为了便于不同的开发商开发各自的产品,Java SE 平台同时为服务提供商设计了统一的接口。只要提供者满足这些接口定义(比如继承某个接口,或者扩展抽象类),服务提供者就能被添加到 Java SE 平台中来。以 图 2 给出的结构为例,服务提供者需要继承 SAXParserFactory、SAXParser 等抽象类,同时将类 VendorSaxParserFactoryImpl 的名字注册到 jaxp.properties 文件中,就可以被使用了。

兼顾了灵活性和效率。通过这种方式,一方面组件提供者和应用开发者开发时绑定到一个约定的接口上,另一方面载入具体哪个组件则是在运行时动态决定的。不同于 Web 服务等技术的完全动态绑定(通过运行时解析 WSDL 文件来决定调用的类型),也不是完全的编码时绑定,这种折衷的方式提供了松耦合、高扩展性,同时也保证了可接受的效率。XML 框架介绍

Java SE 6 平台提供的 XML 处理主要包括两个功能:XML 处理(JAXP,Java Architecture XML Processing)和 XML 绑定(JAXB,Java Architecture XML Binding)。JAXP 包括 SAX 框架 —— 遍历元素,做出处理;DOM 框架 —— 构造 XML 文件的树形表示;StAX 框架 —— 拖拽方式的解析;XSLT 框架 —— 将 XML 数据转换成其他格式。JAXB 则是负责将 XML 文件和 Java 对象绑定,在新版 JDK 中,被大量的使用在 Web 服务技术中。

SAX 框架(Simple API for XML)

SAX 全称 Simple API for XML,该框架使用了事件处理机制来处理 XML 文件,图 3 展示了这个过程。

图 3. SAX 框架处理 XML 文件的流程

SAXParser 将 XML 文件当作流读入。当 parser 遇到 Element_A,就会产生一个事件,然后将该事件发送给处理类。SAX 框架的一大特点是对于节点的处理是上下文无关的。比如 图 3 中 SAXParser,允许注册一个处理类,这个处理类对于所有节点并不加以区分,对他们的处理过程都是一致的。一般包括 startElement 和 endElement 等动作。清单 2 给出了处理类的 startElement 动作的伪代码。

清单 2. 处理类的 startElement 动作的伪代码

1 CLASS Listener < DefaultListener

2 PROCEDURE StartElement(…)

3 IF ( node->Obj.name == ‘Node’ )

4 // Do some calculation

5 FI

6 END

7 END

8 SAXParser->SetListener(new Listener)

使用 SAX 框架,对于 Node 节点的处理并不会根据其前驱或者后缀节点的不同而有所区别。伪代码 3-5 行说明了这一点。一旦发现节点名称是 Node,则进行预定的处理。这个框架本身并不支持对节点进行上下文相关的处理,除非开发者另外维护一些数据结构来记录上下文状态。正是由于 SAX 框架不需要记录的状态信息,所以运行时,SAX 框架占用的内存(footprint)比较小,解析的速度也比较快。

DOM 框架(Document Object Model)

DOM 框架的全称是 Document Object Model。顾名思义,这个框架会建立一个对象模型。针对每个节点,以及节点之间的关系在内存中生成一个树形结构。这个特点与 SAX 框架截然相反。需要注意的是,DOM 框架提供的对象树模型与我们通常理解的 XML 文件结构树模型是有一定的区别的。图 4 给出了一个 XML 文件的结构。

图 4. DOM 框架的对象模型

图 4 中的 Element_B 具有 清单 3 这样的结构:

清单 3. Element_B 的 XML 结构

<Element_B>This is start of Element_B

<Node>…</Node>

This is end of Element_B

</Element_B>

按照 图 4 和 清单 3 给出的结构,一般的对象的观点理解,Element_B 包含子元素 Node,而两句话”This is start of Element_B”与”This is end of Element_B”是 Element_B 节点的内容。而实际上,当针对 Element_B 调用 Element.getContent,得到的是 Element_B 这个名字本身,两句文本同 Node 一样,也是作为子节点的。可以这样认为,DOM 的对象模型,在内存中模拟的是 XML 文件的物理存储结构,而不是节点间的逻辑关系。DOM 中结点的类型也是通过 getContent 返回的节点名字符串区别的。当客户端识别节点类型时,通常会形成以下的代码片断:

清单 4. 使用 DOM 框架的客户端代码

name = Element.getContent

SWITCH name

CASE Element_A:

// Do something

BREAK

CASE Element_B:

// Do something

BREAK

DEFAULT:

END

这种方式是很明显的早绑定 —— 编码时 / 编译时绑定,而不是面向对象语言中使用的运行时绑定技术 —— 继承带来的虚拟函数特性。这个问题的产生和 DOM 框架的设计目标有关。DOM 的目标是一个编程语言无关的,用来处理大段复杂 XML 文件的框架(参见 参考资源),比如书籍和文章。DOM 框架一个显著的特征是善于处理节点与文本混合的 XML 文件(Mixed-Content Model)。这种设计使得 XML 形成树的过程是一个直接映射,不需要进行概念上的转换,也就节省掉很多的处理细节,一定程度上提高了效率。这一点在处理大文件时比较明显,兼顾了效率和上下文状态问题。另一方面,由于编程语言无关的设计目标,也决定了放弃虚函数机制是必要的。

孩子晚饭不消化怎么办
小便发黄吃什么水果
宝宝反复发高烧怎么办
小便黄赤失禁是什么原因
分享到: