dev2dev 首页 > 资源中心 > 技术文章
在Web服务客户机和用户界面中使用XMLBean
该项技术的价值主张
Web服务可以利用XML的能力在各不相同的应用程序中传送复杂数据。但是,如果您的Web服务客户端无法理解XML文档,那么就无法利用Web服务的这个主要优势。输入XMLBean,因为XMLBean是大小写敏感的,您就可以得到由Web服务提供的大量XML信息。
本文可以分为两个部分。首先我会概述XMLBean的内容,解释XMLBean的概念,如何创建XMLBean以及如何在Web服务客户端与其他应用程序中使用它们。然后,我将在实例中使用XMLBean,通过Google的Web服务客户端来展现XMLBean的能力。
第 1 部分:XMLBean
什么是XMLBean?
XMLBean本质上是一种处理XML文档的Java类型。但是XMLBean与传统的DOM和基于指针的API有所不同,因为它具备很强的类型感知能力。使用传统的API解析器,您在识别XML文档时或多或少是带有盲目性的,无法了解特定XML文档的丰富结构。传统的解析器只能识别XML中的父节点、子节点和兄弟节点,但是对于更强的功能就束手无策了。例如,传统的解析器可以按下列方式提取数据。XML文档如下:
创建以下XML文档:
<books>
<book>
<title>David Flanagan</title>
<author>Java in a Nutshell</author>
</book> </books>
|
XMLBean是类型感知的,或者可以说是“强类型的”,因为他们是基于XML Schema的。一个XMLBean可以识别出其Schema中的数据类型和设定规则。
创建XMLBean
XMLBean类编译自一个XML Schema文件(XSD文件)。通过编译,构造了XMLBean,它可以识别出包含于Schema中的数据类型和设定规则。经编译的XMLBean可以解析任何与其Schema相一致的XML文档。
使用BEA的WebLogic Workshop 8.1创建XMLBean的方法是将Schema文件置于一个Schema项目中,并且编译此项目。结果可以得到一套XMLBean的Java类型,每种类型都有丰富的API。下列Schema文件,BookList.xsd,可以编译成三种XMLBean的Java类型:MyBooks、BookArray和Book,它们中的每一个都具备丰富的API,可以识别数据类型。
BookList.xsd
<?xml version="1.0"?> <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:typens="MySchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="MySchema">
<xsd:complexType name="myBooks">
<xsd:all>
<xsd:element name="books" type="typens:BookArray"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="BookArray">
<xsd:sequence>
<xsd:element name="book" type="typens:book" nillable="true"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence> </xsd:complexType>
<xsd:complexType name="book">
<xsd:all>
<xsd:element name="title" type="xsd:string"/>
<xsd:element
name="author" type="xsd:string"/>
</xsd:all> </xsd:complexType>
</xsd:schema> |
上述三种Java类型可以在XMLBean的类文件夹中看到:
在应用程序中使用XMLBean
如果您已经将Schema编译进XMLBean的类中,那么您可以使用XMLBean类来创建并且/或者处理任何与Schema一致的XML文档。在以SOAP
XML文档通信的Web服务应用程序中,这尤其是一个强有力的技巧。本节的剩余部分将展示(1)如何在Web服务中使用XMLBean类以及(2)如何在Web服务客户端中使用XMLBean类。整个过程中,我将使用下面的简单XML
Schema,HelloWorld.xsd:
HelloWorld.xsd
<?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="HelloWorldSchemaTypes">
<xs:element name="HelloMessage" type="xs:string"/>
</xs:schema> |
为了让您了解这个Schema是多么的简单,我将提供两个与此Schema相一致的XML文档:
<HelloMessage> Hello, World! </HelloMessage>
<HelloMessage> Hello, Moon!
</HelloMessage> |
当HelloWorld.xsd被编译时,可以生成一个XMLBean类:helloWorldSchemaTypes.HelloMessage。

(1)在Web服务中使用XMLBean
在Web服务中,XMLBean类主要用于创建新XML文档并且通过调用Web服务方法返回这些文档。使用XMLBean类创建新XML文档的基本过程如下。
1.编写一个Schema文件(.xsd文件),设置您的XML文档所要遵循的规则。下述文档描述完成此任务的一种方式:“How Do I: Generate
Schema from an XML Instance Document?”
2.在Schema项目中保存Schema文件。
3.编译Schema项目。
4.将创建的XMLBean类导入Web服务中。
| import mySchema.MyXMLBeanClass; |
5.通过调用XMLBean类中的方法创建并且操作新的XML文档。通过每个XMLBean类中的Factory.newInstance()方法创建新的实例文档。
// Create a new XML document MyXMLBeanClass doc =
MyXMLBeanClass.Factory.newInstance(); //Modify the
XML document doc.setText("My response message."); |
6.使用Web服务的方法和/或回调,可以将XMLBean类型传给客户端。(相关XML文档将作为SOAP文档的有效负载来传递。)
下列Web服务使用XMLBean类的HelloMessageDocument来为每个客户请求创建XML文档。导入helloWorldSchemaTypes.HelloMessageDocument:
public class HelloWorld implements com.bea.jws.WebService
{ /** * @common:operation
*/ public HelloMessageDocument
hello(String who) {
// Create a new XML document
HelloMessageDocument message = HelloMessageDocument.Factory.newInstance();
// Modify the XML document
message.setHelloMessage("Hello, " + who);
return message;
}
} |
如果客户端提供了参数“World!”,Web服务将创建下列XML文档。
<HelloMessage>
Hello, World! </HelloMessage> |
注意,Web服务方法可以将XMLBean类型返回给其客户端:HelloMessageDocument。当Web服务返回一个XMLBean类型时,原始的Schema(创建XMLBean的Schema)
自动在Web服务的WSDL文件中提供。这就允许Web服务的客户端在终端复制XMLBean类。这也将Web服务和它们的客户端在数据类型方面相一致。
(2)在Web服务的客户端使用XMLBean
在Web服务客户端中,XMLBean主要用来从SOAP XML文档中解析、操作并且提取数据,其中SOAP XML文档由Web服务返回。
在Web服务的客户端解析并且提取SOAP XML文档中数据的基本过程如下:
1.获取由Web服务主机发出的SOAP XML消息的Schema文件(.XSD文件)。某些情况下,您可以仅仅将Web服务的WSDL文件看作是Schema文件(.XSD文件)。在这些情况下,您可以将WSDL保存于您的Schema项目中,并且直接从WSDL编译出XMLBean类。

但是,在其他情况下,WSDL包含由WSDL特定类型的参考语法,您必须以其他方式获取Schema文件。WSDL特定语法的例子请见下面对数组类型的引用。
| <xsd:attribute ref="soapenc:arrayType"
wsdl:arrayType="typens:ResultElement[]"/>. |
1.如果您不能直接使用WSDL文件编译XMLBean类,那么下列文档示出了从实例XML文档中创建Schema文件的一种方式:“How Do I: Generate
Schema from an XML Instance Document?”
2.在Schema项目中保存Schema(或者WSDL)文件。
3.编译Schema项目。
4.将XMLBean类导入Web服务客户端。
| import mySchema.MyXMLBeanClass; |
假定从Web服务传来的SOAP XML消息与Schema文件相一致,您可以在它们从Web服务主机到达时将其解析成XMLBean。
| MyXMLBeanClass message = helloWorldControl.hello();
|
第 2 部分:通过 Google Web服务使用XMLBean
在继续本文之前,推荐您下载Google软件开发包并且获取Google Web API的许可之匙。Google为了使其搜索引擎应用的范围更广,提供了其搜索引擎的Web服务接入点。WSDL文件描述了此Web服务:http://api.google.com/GoogleSearch.wsdl.
通过上述Web服务,任何可以处理XML文档并且在Internet上通信的软件就可以成为Google Web服务的一个客户端。
您构建的下述应用程序将会具有如下架构。Web服务控件将会使用Google Web服务处理SOAP流量。它也将这些SOAP文档解析为XMLBean形式,并且传递给应用程序的用户界面,为呈现给用户做进一步处理。

使用Google Web的示例SOAP请求/响应
下面提供Web服务控件和Google Web服务之间的一个示例SOAP请求/响应交换。一个请求至少需要包含两个参数:查询条件和开发商许可证。在下列请求中,查询条件为:“Plato”,返回结果的最大值被限于2。
调用doGoogleSearch方法:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<ns:doGoogleSearch xmlns:ns="urn:GoogleSearch">
<key xsi:type="xsd:string">xxxXXXxxxXXXxxxXXXxxx</key>
<q
xsi:type="xsd:string">Plato</q>
<start xsi:type="xsd:int">0</start>
<maxResults xsi:type="xsd:int">2</maxResults>
<filter
xsi:type="xsd:boolean">false</filter>
<restrict xsi:type="xsd:string"></restrict>
<safeSearch xsi:type="xsd:boolean">false</safeSearch>
<lr
xsi:type="xsd:string"></lr>
<ie xsi:type="xsd:string"></ie>
<oe xsi:type="xsd:string"></oe>
</ns:doGoogleSearch> </SOAP-ENV:Body>
</SOAP-ENV:Envelope> |
得到下述SOAP响应:
上述请求创建了下面的响应文档。正如您所看到的,在响应文档中的XML是相当复杂的,我们正好可以使用XMLBean来处理它。但是,您如何才能获取能够识别响应文档内部数据类型的Schema呢?下面的步骤指导将演示如何获得Schema以及如何解析响应文档。
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:doGoogleSearchResponse SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="urn:GoogleSearch">
<return xsi:type="ns1:GoogleSearchResult">
<documentFiltering xsi:type="xsd:boolean">false</documentFiltering>
<estimatedTotalResultsCount xsi:
type="xsd:int">743000</estimatedTotalResultsCount>
<directoryCategories ns2:arrayType="ns1:DirectoryCategory[1]"
xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding
/" xsi:type="ns2:Array">
<item xsi:type="ns1:DirectoryCategory">
<specialEncoding xsi:type="xsd:string"></specialEncoding>
<fullViewableName
xsi:type="xsd:string">
Top/Society/Philosophy/Philosophers/Plato</fullViewableName>
</item>
</directoryCategories>
<searchTime xsi:type="xsd:double">0.233717</searchTime>
<resultElements ns3:arrayType="ns1:ResultElement[2]"
xmlns:ns3="http://schemas.xmlsoap.org/soap/encoding
/" xsi:type="ns3:Array">
<item xsi:type="ns1:ResultElement">
<cachedSize
xsi:type="xsd:string">24k</cachedSize>
<hostName xsi:type="xsd:string"></hostName>
<snippet xsi:type="xsd:string"><b>
Plato</b>. <b>...</b>
Before giving details of <b>Plato's</b> life we
will take a few moments<br> to discuss how definite the details
are which we give below.
<b>...</b> </snippet>
<directoryCategory xsi:type="ns1:DirectoryCategory">
<specialEncoding
xsi:type="xsd:string"></specialEncoding>
<fullViewableName xsi:type="xsd:string">Top/Science/Math/History/People
</fullViewableName>
</directoryCategory>
<relatedInformationPresent
xsi:type="xsd:boolean">true<
/relatedInformationPresent>
<directoryTitle xsi:type="xsd:string"><b>Plato</b>
(427-347 BC)</directoryTitle>
<summary xsi:type="xsd:string">"... the reality which
scientific thought
is seeking must be expressible in mathematical terms,
mathemati...</summary>
<URLxsi:type="xsd:string">http://www-gap.dcs.st-and.ac.uk/~history/
Mathematicians/Plato.html
</URL>
<title xsi:type="xsd:string"><b>Plato</b></title>
</item>
<item xsi:type="ns1:ResultElement">
<cachedSize xsi:type="xsd:string">3k</cachedSize>
<hostName xsi:type="xsd:string"></hostName>
<snippet xsi:type="xsd:string">Stanford Encyclopedia of
Philosophy.
Edited by Edward N. Zalta Editorial<br> Information.
[Link to the local table of contents] Table of Contents <
b>...</b> </snippet>
<directoryCategory xsi:type="ns1:DirectoryCategory">
<specialEncoding xsi:type="xsd:string"></specialEncoding>
<fullViewableNamexsi:type="xsd:string">
Top/Society/Philosophy/Reference
/Stanford_Encyclopedia_of_Philosophy
</fullViewableName>
</directoryCategory>
<relatedInformationPresent xsi:type="xsd:boolean">true
</relatedInformationPresent>
<directoryTitle xsi:type="xsd:string">Stanford Encyclopedia
of Philosophy
</directoryTitle>
<summary xsi:type="xsd:string">Online philosophy reference
work,
articles are authored and updated by experts in the field.
Edited...</summary>
<URL xsi:type="xsd:string">http://plato.stanford.edu/</URL>
<title xsi:type="xsd:string">Stanford Encyclopedia of Philosophy</title>
</item>
</resultElements>
<endIndex xsi:type="xsd:int">2</endIndex>
<searchTips xsi:type="xsd:string"></searchTips>
<searchComments xsi:type="xsd:string"></searchComments>
<startIndex xsi:type="xsd:int">1</startIndex>
<estimateIsExact xsi:type="xsd:boolean">false</estimateIsExact>
<searchQuery xsi:type="xsd:string">Plato</searchQuery>
</return>
</ns1:doGoogleSearchResponse>
</SOAP-ENV:Body> </SOAP-ENV:Envelope>
|
一步一步的指导
第1步:设置
在WebLogic Workshop中,选择File-->New-->Application。
在New Application对话框的右边窗格中,选择Default Application。根据您的喜好完成其余对话框的选择。
第2步:为Google搜索结果创建Schema和XMLBean类型
在许多情况下,可以通过编译Web服务中的WSDL来捕获Web服务中数据类型的XMLBean版本:但是Google的WSDL不属于上述情况。
您不能从Google的WSDL中直接编译XMLBean类,因为您使用特定于SOAP的语法来描述数组类型(XMLBean目前仅仅支持Schema类型):
<xsd:complexType name="ResultElementArray">
<xsd:complexContent>
<xsd:restriction
base="soapenc:Array">
<xsd:attribute ref="soapenc:arrayType"
wsdl:arrayType="typens:ResultElement[]"/>
</xsd:restriction>
</xsd:complexContent> </xsd:complexType>
<xsd:complexType name="DirectoryCategoryArray">
<xsd:complexContent>
<xsd:restriction
base="soapenc:Array">
<xsd:attribute ref="soapenc:arrayType"
wsdl:arrayType="typens:DirectoryCategory[]"/>
</xsd:restriction>
</xsd:complexContent> </xsd:complexType>
|
由于这个原因,您必须为Google Web服务创建XML Schema,以此来捕获服务返回的数据类型。通过检查服务返回的SOAP消息并且编辑相应的原始WSDL文件,可以得到目标XML
Schema文件。
GoogleSearch.xsd
<?xml version="1.0"?> <!--
This schema describes data types returned by the Google Web
service, based on the WSDL published at http://api.google.com/GoogleSearch.wsdl.
--> <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:typens="urn:GoogleSearch"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:GoogleSearch">
<xsd:complexType name="DirectoryCategory">
<xsd:all>
<xsd:element name="fullViewableName" type="xsd:string"/>
<xsd:element name="specialEncoding"
type="xsd:string"/> </xsd:all>
</xsd:complexType>
<xsd:complexType name="DirectoryCategoryArray">
<xsd:sequence>
<xsd:element name="DirectoryCategory" type="typens:DirectoryCategory"
nillable="true" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="GoogleSearchResult">
<xsd:all>
<xsd:element name="documentFiltering"
type="xsd:boolean"/>
<xsd:element name="searchComments" type="xsd:string"/>
<xsd:element name="estimatedTotalResultsCount"
type="xsd:int"/>
<xsd:element name="estimateIsExact"
type="xsd:boolean"/>
<xsd:element name="resultElements"
type="typens:ResultElementArray"/>
<xsd:element name="searchQuery"
type="xsd:string"/>
<xsd:element name="startIndex"
type="xsd:int"/>
<xsd:element name="endIndex"
type="xsd:int"/> <xsd:element
name="searchTips"
type="xsd:string"/>
<xsd:element name="directoryCategories"
type="typens:DirectoryCategoryArray"/>
<xsd:element name="searchTime"
type="xsd:double"/>
</xsd:all> </xsd:complexType>
<xsd:complexType name="item">
<xsd:all>
<xsd:element name="summary" type="xsd:string"/>
<xsd:element name="URL"
type="xsd:string"/>
<xsd:element name="snippet" type="xsd:string"/>
<xsd:element name="title"
type="xsd:string"/>
<xsd:element name="cachedSize" type="xsd:string"/>
<xsd:element name="relatedInformationPresent"
type="xsd:boolean"/>
<xsd:element name="hostName" type="xsd:string"/>
<xsd:element name="directoryCategory"
type="typens:DirectoryCategory"/>
<xsd:element name="directoryTitle" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="ResultElementArray">
<xsd:sequence>
<xsd:element name="item" type="typens:item" nillable="true"
minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence> </xsd:complexType>
</xsd:schema> |
在Schema项目中保存Schema文件GoogleSearch.xsd并对其进行编译,则生成下述五个XMLBean类:

第3步:从WSDL文件中创建Web服务控件
在这一步中,您将自动从Web服务的WSDL文件中生成Web服务控制文件。Web服务控件处理客户端与Google Web服务之间的SOAP流量。它可以向Web服务发送SOAP消息请求,监听SOAP响应并且将它们转发至界面。在这一步中,我们在将SOAP响应响应转发至用户界面之前,先构建把SOAP消息转换成XMLBean类型的Web服务。
在您的Web应用程序项目中保存WSDL文件(位于http://api.google.com/GoogleSearch.wsdl)。
右击WSDL文件并选择Generate Service Control。
在Generate using XmlBean对话框中,选择Yes。

Web服务控制文件GoogleSearchControl.jcx被创建。选择Yes,就可以使用Web服务控件的方法来返回XMLBean类型。例如,下述GoogleSearchControl.jcx的方法可以返回XMLBean类型(GoogleSearchResult)。
public googleSearch.GoogleSearchResult doGoogleSearch
(java.lang.String key,
java.lang.String q,
int start, int maxResults, boolean filter,
java.lang.String restrict, boolean safeSearch,
java.lang.String lr, java.lang.String ie,
java.lang.String oe); |
第4步:创建用户界面
现在可以查询Google搜索引擎并获取XMLBean形式的响应。最后一步就是创建用户界面,以有用且直观的方式解析并且显示这些结果。不论您的用户界面如何,由于搜索结果是XMLBean形式的,您拥有丰富的API来提取响应的数据。
例如,您可以使用下列代码打印出所有的<title> 元素:
// Query the control method
googleSearch.GoogleSearchResult
results =
myControl.doGoogleSearch(...supply parameters here...);
// Print out the URLs to
the console for(int i = 0;
i < results.getResultElements().getItemArray().length; i++)
{
System.out.println( results.getResultElements().getItemArray(i).getURL()
); } |
JSP页面的XMLBean数据绑定
您也可以在JSP页面中使用XMLBean。使用WebLogic Workshop的“数据绑定”技术,您可以在JSP页面中调用Java类型,而不在JSP页面上放置Java代码。这一点很大程度上实现了Web应用程序中的代码与界面的分离。但是,由于JSP页面以类型感知的方式调用Java数据,所以JSP页面中仍然保留类型感知能力,这会为您提供很大方便。
例如,假设您在页面流文件(带有JPF扩展的Java文件)中使用下面的XMLBean数据。
googleSearch.GoogleSearchResult results = myControl.doGoogleSearch(...supply
parameters here...);
您可以使用WebLogic Workshop的一种特殊的具有数据绑定功能的标签来绑定JSP页面和Java数据。(这些标签以前缀“netui”开始)。
| <netui:content value="{pageFlow.results.resultElements.itemArray[0].URL}"
/> |
需要注意的是,这个JSP标签不包括Java代码(使用的表达语言是ECMA脚本),但是它在表达式“pageFlow.results.resultElements.itemArray[0].URL”中保持了Java的类型感知能力。
作者其它文章
|