XML API与Web服务

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 文件的流程

图 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. 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 形成树的过程是一个直接映射,不需要进行概念上的转换,也就节省掉很多的处理细节,一定程度上提高了效率。这一点在处理大文件时比较明显,兼顾了效率和上 下文状态问题。另一方面,由于编程语言无关的设计目标,也决定了放弃虚函数机制是必要的。

StAX 框架(Streaming API for XML)

    SAX 框架的缺点是不能记录正在处理元素的上下文。但是优点是运行时占内存空间比较小,效率高。DOM 框架由于在处理 XML 时需要为其构造一棵树,所以特点正好相反。StAX 框架出现于 Java SE 6 中,它的设计目标就是要结合 SAX 框架和 DOM 框架的优点。既要求运行时效率,也要求保持元素的上下文状态。清单 5 是一段使用 StAX 框架处理 XML 文件的代码。


清单 5. 使用 StAX 框架处理 XML 文件

                
import java.io.*;

import javax.xml.stream.*;
import javax.xml.stream.events.*;

public class StAXTest {

    public static void main(String[] args) {
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        InputStream input = new ByteArrayInputStream(
            ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
		    "<work-contact-info>" +
			"<Location>Shanghai-shuion-333</Location>" +
			"<Postal>200020</Postal>" +
			"<Tel><fix>63262299</fix><mobile>1581344454</mobile></Tel>" +
			"<Appellation>Mr. Wang</Appellation>" +
			"</work-contact-info>").getBytes());
        try {
            XMLEventReader xmlEventReader = inputFactory.createXMLEventReader(input);
			while (xmlEventReader.hasNext()) {
                XMLEvent event = xmlEventReader.nextEvent();

                if (event.isStartElement()) {
					StartElement startElement = event.asStartElement();
                    System.out.println(startElement.getName().toString());
                }

                if (event.isCharacters()) {
                    Characters text = event.asCharacters();
                    if (!text.isWhiteSpace()) {
                        System.out.println("\t" + text.getData());
                    }
                }
            }
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }
    }
}

 

    观察后可以发现 StAX 框架和 SAX 框架具有相似的地方。StAX 有 Event.isStartElement 方法,SAX 有 DefaultHandler.startElement 方法。StAX 有 Event.isCharacter 方法,SAX 有 DefaultHandler.character 方法。实际上这两个框架处理 XML 文件的时候使用了相似的模型——将 XML 文件作为元素组成的流,而不同于 DOM 的树模型。解析 XML 文件时,应用程序调用 XMLEventReader 的 nextEvent 方法解析下一个元素(或者是解析同一个元素,根据解析的不同阶段,产生不同元素),StAX 就会通过 XMLEventReader 产生一个事件。比如针对同一个元素,可能会产生 StartElement 和 EndElement 事件。形象的说 XMLEventReader 就像是一根绳子,拽一下,解析一个元素,产生一个事件。于是这种技术也被称为”Pull Parser”技术。StAX 在处理 XML 文件时,产生的所有事件是通过一个 Iterator(XMLEventReader 继承了 Iterator)返回的。应用程序通过这个 Iterator 能知道某个解析事件的前后分别是什么。这类信息就是一个元素的上下文信息。

    XSLT 数据转换框架(The Extensible Stylesheet Language Transformations APIs)

一 般来说 XML 文件格式被认为是一种很好的数据交换 格 式。于是 Java SE 6 SDK 基于以上介绍的三种 XML 处理机制,提供了一个 XML 转换框架。XSLT 框架负责进行转换 —— 包括将 XML 文件转换成其他形式如 HTML,和将其他形式的文件转换成 XML 文件。更进一步说,这个框架可以接受 DOM 作为其输入和输出;可以接受 SAX 解析器作为输入或者产生 SAX 事件作为输出;可以接受 I/O Stream 作为输入和输出;当然也支持用户自定义形式的输入和输出。图 5 显示了这种依赖关系:


图 5. XSLT 框架的依赖关系

图 5. XSLT 框架的依赖关系

转换框架的输入输出对象的类型并不要求是一一对应的。比如,使用 DOMSource 做为输入,可以使用 StreamResult 作为输出。清单 5 是一段伪代码,用来显示 JDK 将不同 javax.xml.transform.Source 转换成不同 javax.xml.transform.Result 子类型的过程:


清单 5. JDK 转换框架的转换过程

                
// Construct input
1. factory = XMLParserDocumentFactory->NEW
2. parser = factory->NewParser
3. document = parser->Parse(File)

// Wrap input/output
4. source = Source->NEW( document )
5. sink = Result->NEW

// Construct transformer
6. tFactory = TransformerFactory->NEW
7. transformer = tFactory->NewTransformer

// Transform
8. transformer->Transfer( source, sink) 

    通过这个过程的转化,一个 javax.xml.transform.Source 可以转化成为类型 javax.xml.transform.Result。JDK 提供了如 图 5 所示的 4 种 Result 子类型,用户也可以定义自己的 Result 类型。另一方面,用户自定义的数据解析器或者数据文件,也可以作为 Transformer 的输入。下面一个例子,针对一个数据文件,首先生成了一棵 DOM 树,然后又根据这棵 DOM 树,提取了所有的联系信息,生成了一个文本文件。清单 6 给出了这个数据文件:


    清单 6. 地址信息文件

                
work contact-info
 Location	Shanghai-shuion-333
	Postal	200020
	Tel
		fix		63262299
		mobile	1581344454
	Appellation	Mr. Wang

 

    清单 7 为这个信息文件构造一个 DOM 树,并将其作为 transformer 的输入。


    清单 7. 构造 DOM 树

                
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

class ContentHandler extends DefaultHandler {

    @Override
    public void characters(char[] ch, int start, int length) 
		throws SAXException {
		String name = new String(ch, start, length);
        System.out.print(name + "\t");
    }
}

public class DOMTest {

    /**
    * @param args
    * @throws TransformerException
    */
    public static void main(String[] args) {

        try {
            DocumentBuilderFactory documentfactory = DocumentBuilderFactory
                .newInstance();
            DocumentBuilder builder = documentfactory.newDocumentBuilder();
            Document document = builder.newDocument();

            Element root = document.createElement("work-contact-info");

            Element loca = document.createElement("Location");
            loca.setTextContent("Shanghai-shuion-333");
            root.appendChild(loca);

            Element postal = document.createElement("Postal");
            postal.setTextContent("200020");
            root.appendChild(postal);

            Element tel = document.createElement("Tel");
            root.appendChild(tel);

            Element fix = document.createElement("fix");
            fix.setTextContent("63262299");
            tel.appendChild(fix);

            Element mobile = document.createElement("mobile");
            mobile.setTextContent("1581344454");
            tel.appendChild(mobile);

            Element appellation = document.createElement("Appellation");
            appellation.setTextContent("Mr. Wang");
            root.appendChild(appellation);

            document.appendChild(root);

            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer transformer;
            transformer = tFactory.newTransformer();
            SAXResult result = new SAXResult();

            ContentHandler cHandler = new ContentHandler();
    		result.setHandler(cHandler);
            transformer.transform(new DOMSource(document), result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

  Java SE 6 SDK 提供了至少以上三种内置的处理 XML 文件的机制。它们分别是 Simple API for XML、Document Object Model 和 Streaming API for XML。其中 SAX 和 StAX 采用了相似的模型 —— 将 XML 文件建模为元素流,DOM 采用了树形模型。带来的结果是 SAX 和 StAX 运行时空间相对 DOM 紧凑。状态保持能力则依次 SAX -> StAX -> DOM 变强。特别值得一提的是 StAX 技术是最新引进的 XML 处理技术,它结合了 SAX 和 DOM 的优点。清单 8 给出了一个粗略度量 SAX、StAX、DOM 三个框架解析同一个 XML 文件的运行效率的代码。


    清单 8. 度量 XML 解析框架的运行时间

                
public class StAXTest {

    public static void main(String[] args) {
        final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
		    "<work-contact-info>" +
			"<Location>Shanghai-shuion-333</Location>" +
			"<Postal>200020</Postal>" +
			"<Tel><fix>63262299</fix>" +
			"<mobile>1581344454</mobile></Tel>" +
			"<Appellation>Mr. Wang</Appellation>" +
			"</work-contact-info>";
        for (int i = 0; i < 10000; i++) {
            StAX(xml);
        }
 
        for (int i = 0; i < 10000; i++) {
            SAX(xml);
        }
 
        for (int i = 0; i < 10000; i++) {
            DOM(xml);
        }
 
        long current = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            StAX(xml);
        }
        current = System.currentTimeMillis() - current;
        System.out.println(current);
 
        current = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
			SAX(xml);
        }
        current = System.currentTimeMillis() - current;
        System.out.println(current);
 
        current = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
			DOM(xml);
        }
        current = System.currentTimeMillis() - current;
            System.out.println(current);
    }

    private static void StAX(final String xml) {
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        InputStream input;
        try {
            input = new ByteArrayInputStream(xml.getBytes());
			XMLEventReader xmlEventReader = inputFactory
                .createXMLEventReader(input);
            while (xmlEventReader.hasNext()) {
                XMLEvent event = xmlEventReader.nextEvent();

                if (event.isStartElement()) {
                    StartElement startElement = event.asStartElement();
                }

                if (event.isCharacters()) {
                    Characters text = event.asCharacters();
                    if (!text.isWhiteSpace()) {
                    }
                }
            }
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }
    }

    private static void SAX(final String xml) {
        SAXParserFactory f = SAXParserFactory.newInstance();
        InputStream input;
        try {
            SAXParser p = f.newSAXParser();
            input = new ByteArrayInputStream(xml.getBytes());
            p.parse(input, new DefaultHandler());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    private static void DOM(final String xml) {
        DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
        InputStream input;
        try {
            DocumentBuilder p = f.newDocumentBuilder();
            input = new ByteArrayInputStream(xml.getBytes());
            p.parse(input);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

得出的数据如下:

 

2734
4953
6516

 

    可以看出解析速度按 SAX -> StAX -> DOM 依次变慢。这组数据从一个侧面反映了这三种技术的特性。SAX 处理小的,简单的 XML 文件更高效。基于三种 XML 解析技术,Java SE 6 SDK 又提供了数据格式转换框架 —— XSLT。同时 XSLT 技术和其他很多的 JDK 框架一样,是一个开放框架。它提供了一些抽象类和接口,让应用程序可以根据需求,开发出不同的 XML 数据处理和转换工具。然后通过之前叙述的 Service Provider 机制,将这些工具“插入”JDK 中。表 1 罗列了 SAX、StAX、DOM、XSLT 在 JDK 中的位置:


表 1. SAX,StAX,DOM,XSLT 在 JDK 中的位置

SAX StAX DOM XSLT
javax.xml.parsers javax.xml.stream javax.xml.parsers javax.xml.transform
  javax.xml.stream.events   javax.xml.transform.dom
  javax.xml.stream.util   javax.xml.transform.sax
      javax.xml.transform.stax
      javax.xml.transform.stream

Web 服务

    基于XML的数据通常被作为 Web 服务之间互相调用的标准的数据传输文件格式。Java SE 6 SDK 中基于 XML 的解析技术,也提供了 Web 服务的 API 支持。和较早的 JDK 5 相比,新版本的 JDK Web 服务功能更改了名称 —— 从 JAX-RPC 变成 JAX-WS。JDK 5 只支持基于 remote-procedure-call 的 Web 服务,JDK 6 在此基础上,还支持基于 SOAP message 的 Web 服务实现。下面将给出一个例子,基于 SOAP message,实现一个简单的 Web 服务。

  1. 清单 9 给出了开发一个 Web services EndPoint 的代码。

    清单 9. 一个 Web service‘Hello’服务
                            
    package hello;
    import javax.jws.WebService;
    import javax.jws.WebMethod;
    import javax.xml.ws.Endpoint;
    
    @WebService
    public class Hello {
        @WebMethod
        public String hello(String name) {
            return "Hello, " + name + "\n";
        }
     
        public static void main(String[] args) {
            // create and publish an endpoint
            Hello hello = new Hello();
            Endpoint endpoint = Endpoint.publish("http://localhost:8080/hello", hello); 
        }
    }
    

  2. 使用 apt 编译 Hello.java,产生辅助文件:

    apt -d sample example/Calculator.java
    

    运行完这条命令之后,example 目录下面多出了一个 jaxws 子目录如 图 6 所示。Apt 工具在该目录里生成了发布 Hello Web service 所必需的两个辅助文件。



    图 6. example 目录
    图 6. example 目录

  3. 发布 Hello Web service:

    java -cp sample hello.Hello
    

    将浏览器指向 http://localhost:8080/hello?wsdl 会产生如 图 7 所示页面。



    图 7. 发布的 Hello Web service
    图 7. 发布的 Hello Web service

    Java SE 6 SDK 内嵌了一个轻量级的 HTTP Server,方便开发者验证简单的 Web service 功能。通过以上三步,一个 Web service Endpoint 就部署完成,下面将开发一个调用 Hello 服务的客户端。

  1. 为 Web 服务的客户端产生存根文件:

    wsimport -p sample -keep http://localhost:8080/hello?wsdl
    

    这将会在 sample 目录下产生如 图 8 所示的文件。这一步实际是根据上面 URL 指向的 WSDL 文件,通过 JAXB 技术,生成了相应的 Java 对象。



    图 8. wsimport 产生的文件
    图 8. wsimport 产生的文件

  2. 开发,编译,运行 Web 服务客户程序。清单 10 给出了使用 Hello 服务的客户程序。



    清单 10. 使用 Hello 服务的客户程序
                            
    package sample;
    class HelloApp {
        public static void main(String args[]) {
            HelloService service = new HelloService();
            Hello helloProxy = service.getHelloPort();
            String hello = helloProxy.hello("developer works");
            System.out.println(hello);
        }
    }
    

    图 9 是编译并运行该客户程序产生的结果:



    图 9. 调用 Hello 服务
    图 9. 调用 Hello 服务

    可以说在 Java SE 6 SDK 中,Web 服务的开发过程被大大简化了。原来开发中需要手工重复劳动产生的文件,可以使用工具自动生成。比如 WSDL 文件可以自动生成,和 WSDL 绑定的 Java 对象也自动生成,部署(本文仅指 JDK 提供的轻量 HTTP server 部署环境)也大大简化。这些全部归功于 JDK 6 中引入的一些新的 JSR 实现,即一些 API 和工具。表 2 给出了 JDK6 中为 Web 服务 API 提供支持的包。


表 2. JDK 中提供 Web 服务 API 支持的包

JSR Package
JSR 224

Java API for XML-Based Web Services 2.0

javax.xml.ws
javax.xml.ws.handler
javax.xml.ws.handler.soap
javax.xml.ws.http
javax.xml.ws.soap
javax.xml.ws.spi
JSR 222

Java Architecture for XML Binding (JAXB) 2.0

javax.xml.bind
javax.xml.bind.annotation
javax.xml.bind.annotation.adapters
javax.xml.bind.attachment
javax.xml.bind.helpers
javax.xml.bind.util
JSR 181

Web Services Metadata for the Java Platform

javax.jws
javax.jws.soap

    除此之外 JDK 6 还提供了一些工具,包括 wsgen, wsimport 以及 Java 调用的轻量级 HTTP server。API 和工具联合提供了一个简单的 Web services IDE 开发环境,可以简化 Web 服务应用的开发。

Java class 和 XML 文件的绑定

    从上一段关于 Web 服务的叙述中,我们能够发现开发和部署 Web 服务的过程中存在多次 Java 对象和 XML 文件转化的过程。比如开发和部署服务的时候,将一个 Web Service EndPoint 发布成为一个 WSDL,或者使用服务的时候,将一个 WSDL 文件转换成一组 Java 对象。所有的转换,都是通过工具自动完成的。这里存在一些问题,Java 对象的类型转换成 XML 元素是需要符合一定的标准,还是随意转换呢?如果按照标准转换,那么这个标准是什么样子的?比如 Java 中的 int 类型是应该变成 <int></int> 呢,还是 <integer></integer>。如 表 2 列出,JSR222- Java Architecture for XML Binding (JAXB) 2.0 标准为这些问题给出了一个规范的解答。

    首先示范一个简单的例子,将根据一个 XML 文件的 schema,转换成 Java 对象。还是以 清单 6 中的数据文件为依据。构造一个 XML schema 文件,如 清单 11 所示。要运行这个例子,首先需要下载 一个 JAXB Reference Implementation jar(下载 请参见 参考资源),并将该 jar 文件加入到 classpath 中。


清单 11. 用于绑定的 workcontactinfo.xsd 文件

                
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<xsd:element name="workcontactinfo" type="workcontactinfo" />
	<xsd:complexType name="workcontactinfo">
		<xsd:sequence>
			<xsd:element ref="Location" maxOccurs="1" minOccurs="1" />
			<xsd:element ref="Postal" maxOccurs="1" minOccurs="1" />			
			<xsd:element ref="tel" maxOccurs="1" minOccurs="1" />
			<xsd:element ref="Appellation" maxOccurs="1" minOccurs="1" />
		</xsd:sequence>
	</xsd:complexType>
	<xsd:element name="tel" type="tel" />
	<xsd:complexType name="tel">
		<xsd:sequence>
			<xsd:element ref="fix" maxOccurs="1" minOccurs="1" />
			<xsd:element ref="mobile" maxOccurs="1" minOccurs="1" />
		</xsd:sequence>
	</xsd:complexType>
	<xsd:element name="Location" type="xsd:string" />
	<xsd:element name="Postal" type="xsd:string" />
	<xsd:element name="Appellation" type="xsd:string" />
	<xsd:element name="fix" type="xsd:string" />
	<xsd:element name="mobile" type="xsd:string" />
</xsd:schema>

 

  1. 运行命令 xjc workcontactinfo.xsd。将会在当前目录下生成一个 generated 子目录。
  2. 运行命令 javac generated\*.java,编译所有生成的 Java 文件。
  3. 操作生成的 Java 对象。清单 12 给出了一个操作生成的 java 对象的例子。要注意,一定要先将 JAXB Reference Implementation jar 放到 classpath 中。


清单 12. 调用生成的 Java 对象

                
import generated.*;

import java.io.FileOutputStream;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class JAXBTest {

    public static void main(String[] args) {
        try {

            JAXBContext jContext = JAXBContext.newInstance("generated");

            ObjectFactory factory = new ObjectFactory();

            Workcontactinfo contactinfo = (Workcontactinfo) (factory
                .createWorkcontactinfo());

            contactinfo.setAppellation("Mr. Wang");
 
            contactinfo.setLocation("Shanghai-shuion-333");
 
            contactinfo.setPostal("200020");

             Tel tel = (Tel) (factory.createTel());
            tel.setFix("123456");
            tel.setMobile("1376666666");
 
            contactinfo.setTel(tel);
            Marshaller marshaller = jContext.createMarshaller();

            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                Boolean.TRUE);

            marshaller.marshal(contactinfo, new FileOutputStream(
                "workcontactinfo1.xml"));

            System.out.println("java tree converted into xml & filed");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

运行这个程序,就能生成一个 XML 数据文件,如 清单 13。


清单 13. XML 数据文件

 

                
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workcontactinfo>
    <Location>Shanghai-shuion-333</Location>
    <Postal>200020</Postal>
    <tel>
        <fix>123456</fix>
        <mobile>1376666666</mobile>
    </tel>
    <Appellation>Mr. Wang</Appellation>
</workcontactinfo>
 回顾一下 Web 服务的 WSDL 文件,如 图 5 所示,是一个符合 W3C XMLSchema 规范的 schema
文件,以及整个过程中生成的 Java 类,我们应该能更好的理解 Web 服务开发,部署,使用的全过程。首先 JDK 6 提供的工具 apt
根据 Web Service EndPoint 中相关的注释生成一些与 WSDL schema 绑定的 Java
类。察看这些类可以发现,它们与 JAXB 例子中 generated 目录下生成的 Java 文件十分相似。接着通过 HTTP 服务将这个
WSDL schema 文件发布出来。然后通过 wsimport 工具,生成一个 Web 服务的客户运行时代理,相当于 清单 12
的功能。最终 Web 服务的用户程序同运行时代理交互,该代理生成并传递形式如 清单 13 的 XML 数据文件。图 10 结合 表 2 给出了
Web 服务开发到使用整个周期的工作流和涉及到的 JDK 包。


图 10. Web 服务开发部署流程中 XML 技术的应用

图 10. Web 服务开发部署流程中 XML 技术的应用





    总结

    比较前一个版本的 JDK,新版本对 XML 处理技术进行了扩展。包括新加入的 StAX 和 JAXB。基于这些新的 XML 数据处理技术,JDK 6 对 Web 服务的支持也得到了大大的增强。这些增强体现在引入了一些注释和 API,增加了更多的工具,可以自动化大部分开发和部署的工作。对于 XML 应用开发者来说,有更多更有力地技术可以选用。对于 Web 服务提供者来说,开发工具更为强大,开发流程更为简化,工作效率得到提高。而对于 Web 服务的使用者,更多的底层细节被屏蔽。可以说,新版 JDK 在对 XML 相关应用开发上的支持,较前一个版本有了很大提升。

 

你可能感兴趣的:(xml,框架,应用服务器,Web,mobile)