月亮的太阳

小乖的BLOG
posts - 114, comments - 41, trackbacks - 0, articles - 27
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

理解Web Services附件

Posted on 2006-02-23 15:39 月亮的太阳 阅读(604) 评论(0)  编辑  收藏
使用XML来传递消息会给您的应用程序带来许多好处:通过它您可以利用大量的API、跨平台支持、以及用来描述和操纵XML(例如XqueryXSLTXPathXML Schema)的通用工具。你不想关心的许多细节问题也可以由XML来处理——比如行结束、字符编码、结构化数据和分界——这使您只需将精力集中于您的应用程序。由于上述所有的原因,能使用XML是非常好的。

尽管用XML来传递消息存在巨大优势,但是其缺点是性能问题:由于XML的设计方式,有些数据类型不能很好的与XML集成。由于XML是基于文本的形式,最显著的是二进制数据(即不能被表示为Unicode字符集的任何东西)。

开发人员要做什么呢?

使用URL引用

最容易的解决办法就是在你的XML中不包括这样的数据,而是像HTML中使用URL那样在Web上引用它。例如,如果你的应用程序的消息需要包含一个人的JPEG图片,那么带有嵌入式链接的XML可能如下所示:

         <?xml version='1.0' ?>

         <soap:Envelope xmlns:soap="...">

             <soap:Body>

                 <Person name="bob">

                   <Picture>http://www.example.com/people/bob.jpg</Picture>

                 </Person>

             </soap:Body>

         </soap:Envelope>

如果数据是长时间稳定且对消息的接收者而言是可用的,这种方式能够发挥很好的作用。然而,如果数据是短暂的,或者数据的接收者没有连接到Web,这就不是一个好的解决办法。为了处理这些情况,数据必须随着消息进行传送。

使用编码

把二进制的数据放入一条基于XML的消息的最简单的方法,就是使用类似Base64的方式对其进行编码,把它转变成对XML 安全的一串字符(以及7位的MIME传输,XML最初就是针对它设计的)。使用Base64编码,我们的图片XML 可能如下所示:

         <?xml version='1.0' ?>

         <soap:Envelope xmlns:soap="...">

             <soap:Body>

                 <Person name="bob">

                   <Picture>Li4uYmluYXJ5IGpwZWcgaW1hZ2UuLi4=</Picture>

                 </Person>

             </soap:Body>

         </soap:Envelope>

XML Schema定义了一种base64Binary类型,这是一种足够通用的方法,使您能够照此识别已编码的二进制内容(它也定义一种hexBinary类型,这是一个可选的编码模式,但还不是很流行)。

这种编码的不利方面是它的低效率;因为数据的二进位形式使用有限范围的字符集来表示丰富的数据流,它通常比base64形式更简洁。通常,对于给定的数据流,base64编码会引入33%的冗余尺寸,从而使XML消息更大。

另外,对二进制数据进行编码和解码会造成相当大的处理开销,这反过来会影响使用它的应用程序的可扩展性和性能。

使用带附件的SOAP消息

这些问题促成了带附件的SOAP消息(SOAP Messages with Attachments (SwA)的开发。带附件的SOAP消息是一种特定于Web Services的技术,它使用MIME Multipart/Related数据包来随XML消息发送二进制数据和其它附件,从而避免了编码的开销。用于我们的图片的一个简化的SwA消息可能如下所示:

         Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml

         --MIME_boundary

         Content-Type: text/xml; charset=UTF-8

         Content-Transfer-Encoding: 8bit

         <?xml version='1.0' ?>

         <soap:Envelope xmlns:soap="...">

             <soap:Body>

                 <Person name="bob">

                     <Picture>cid:bob@pictures.example.com</Picture>

                 </Person>

             </soap:Body>

         </soap:Envelope>

         --MIME_boundary

         Content-Type: image/jpeg

         Content-Transfer-Encoding: binary

         Content-ID: <bob@pictures.example.com>

         ...binary JPEG image...

         --MIME_boundary--

我们可以看到,图像数据在一个MIME附件中。它是从带有一个cidURL)的SOAP消息而被引用的,这个URI使用Content-ID MIME头的值来找到正确的附件。

这样避免了编码的开销和冗余,但是也带来了一些新的问题。XMLWeb Services的大部分价值在于使用generic XML工具来处理内容的能力——像XPatXQueryXSLTXML 加密和数字签名以及XML schema一样。这些工具不处理非XML的内容;如果您想要对这些内容进行查询、转换、加密、签名或者描述,您就需要使用一种不同的机制,甚至建立一种新的机制。

此外,由于SwA还存在相当多的互操作性问题,以致于WS-I一直致力于研究(在写作本文时)适合它们的特定的互操作性配置文件。

实际上,带有附件的SOAP消息引进了一种新的消息数据模型,因此,它不再是基于XML的消息传递了。在2003年的早期,BEA公司Microsoft公司就开始关注并撰写关于这个问题的白皮书,并且开始探索其他可能的选择。

MTOMXOP的引入

在找出与SwA相关的那些问题之后,我们开始研究制订一个具体的解决方案。这项工作从Proposed Addendum to SOAP Messages with AttachmentsPASWA)开始,并且W3C XML协议组(该组提出了SOAP 1.2)一直将它作为Message Transmission Optimization MechanismMTOM)和XML-binary Optimized PackagingXOP)的规范加以研究。

上述内容背后的思想很简单。 XOPXML的可选序列化方法,使您能够将任何XML文档表示为XOP数据包。在XOP数据包里,任何被命名为base64字符串的事物都作为附件进行编码,其方法与SwA的方法非常相似。不过,数据和附件之间的链接不同:它不是依靠应用程序进行处理,而是由该格式自行处理。

例如,当我们图片文档在作为一个XOP数据包而被序列化时,可能如下所示:

         Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml

         --MIME_boundary

         Content-Type: text/xml; charset=UTF-8

         Content-Transfer-Encoding: 8bit

         <?xml version='1.0' ?>

         <soap:Envelope xmlns:soap="..."

          xmlns:xbinc="...">

             <soap:Body>

                 <Person name="bob">

                     <Picture><xbinc:Include            

                               href="cid:bob@pictures.example.com"/></Picture>

                 </Person>

             </soap:Body>

         </soap:Envelope>

         --MIME_boundary

         Content-Type: image/jpeg

         Content-Transfer-Encoding: binary

         Content-ID: <bob@pictures.example.com>

         ...binary JPEG image...

         --MIME_boundary--

XML观点来看,该文档与上面的base64版本同构;也就是说,其中任何一种都可以编码为另外一种,而不会造成信息的丢失。与SwA不同,XOP使用xbinc:Include元素显式地将内容与正确的附件关联起来,并避免了SwA中存在的许多歧义性。它也保持XML 消息的数据模型;因为它只是XML的一种可选编码,实际上,可以将附件中的二进制内容视为XML自身中的base64编码的数据。

XOP是一个通用的机制;我们能用它来序列化任何种类的XML。在SOAPMTOM使XOP串行化和反串行化成为可能,这是HTTP绑定的扩展。随着其他绑定被定义出来,它们也将包含XOP支持。

API角度来看,XOP隐含着一些有趣的内容。如果一个XML栈能够理解XOP编码,那么您的应用程序就根本不需要改变;例如,当它需要访问图片时,它仍然能够将所获得内容的字符值看作base64编码字符串。如果XOP正在使用中,那么该实现可以即刻自动将其编码。

这就能够将XOP透明地逐步部署到应用程序中,但是并不能产生期望的性能收益。为了产生期望的性能收益,应用程序需要通过使栈显式地为它执行base64编码和解码来访问二进制内容的值空间,而不是词法空间

实际上,这相当容易做到。为了兼容XOP,需要用一种简单方法来扩展XML API,从而访问值空间。例如,SAX定义了characters()方法来处理字符数据,包括我们的图片元素。通过定义一种新方法——例如binary() 方法,自动地对base64编码的内容进行合适的解码, 或者当xbinc:Include 存在时,取消对附件的引用。应用程序可以更容易地实现由XOP提供的收益。

当我们考虑类型感知API,(像XML beans)时,事情变得更有意思了。因为它提供了访问XML 内容的词法空间和值空间的方法,所以有可能在类似XOP的类型感知编码中进行无形的分层。

建议

在写作本文时,W3C仍然在开发XOPMTOM,但是它们进展迅速,并且拥有来自Web服务行业的各个巨头的充分支持。因此,我们预计XOPMTOM将成为主流的Web Services附件机制。

另外,XML API——包括DOMSAXStAXXML beans——将需要进行修改,以实现由XOP带来的好处。由于XOP得到Web Services领域的一致认同及其简洁性,我们期望这种修改会迅速实现。

同时,最好的选择是使用一个URI引用和编码;对于某些应用程序类型而言,URI引用总是有用的,并且编码与XOP的透明兼容性意味着,当XOP得到更广泛的采用时,很容易进行升级。


只有注册用户登录后才能发表评论。


网站导航: