![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
上一篇blog里提到过,WSDL规范其实就好比是我们国家的法侓,它规定了公民(好比是SOAP消息)应该要怎么行使个人权力以及履行个人义务等,即具有指导性的意义。用比较规范的语言来说就是WSDL是用来描述一个异构组件如何被程远程未知平台调用的,即描述了SOAP消息的格式,在WEB服务中起到了服务端和服务客户端之间的契约作用。
在系列的第一篇文章里已经提到,系统的目标是:Web 服务客户机在事先不了解一个 Web 服务的组成的情况下可以动态地发现和调用该Web 服务。
那么,我们需要做什么才能动态地发现和调用这个服务?
首先,需要发现来自系统的服务资源库里关于此服务的信息,这个就是我在系列(六):
Web服务搜索与执行引擎(六)--基于Lucene的Web服务检索
中写到的关于Web服务搜索模块如何从库里提取服务信息,一个最重要的信息是服务所对应的WSDL 文档的URL。
其次,需要阅读来自服务提供者的 WSDL文档并进行解析,以获取各种信息。这一步就是本篇文章所要关注的。
最后,我将拥有足够的信息来使用SAAJ发送和接收对 Web 服务实现的 SOAP 请求。这一步就是在后续文章里将要写到的。
那么我们就来看看如何阅读来自服务提供者的 WSDL文档并进行解析?
WSDL的常用处理方法:
- 基于 DOM 的方法:上一篇blog也说到了, WSDL 文件从本质上来讲是一个 XML 文件,现有的 DOM API(例如 Xerces)能够用来进行解析或者构建 WSDL 文件。这种方法是最通用的,但同时也是处理 XML 文件最费力的方法。尽管从技术上来讲是可行的,基于 DOM API 的实现对于代码敏感且容易出错。同时,这一解决方法迫使您不得不处理两个完全不同的模型:DOM 和 WSDL 模型。
- 基于特定 API 的方法:利用 IBM 的 WSDL4J 来实现 WSDL 操作。这种方法倾向于 WSDL 模型,它允许您直接操作 WSDL 。这种方法的不足在于您不仅要处理 WSDL 本身,还要处理 WS-Addressing、WS-Policy 和扩展脚本。它同时还使用那些尚未成为标准的事物,这就意味着现有的一些 API 将会改变。这就意味着这种基于特定 API 的方法不得不掺杂一定数量的 DOM 处理。但是这些不足跟前面提到的“倾向于 WSDL 模型,它允许您直接操作 WSDL”的好处比起来,我们还是觉得使用它是当前的最好选择。
- 基于 Java 生成的方法:因为描述我们实现的所有脚本都是标准的 XML 脚本,因此可以生成对应于这些脚本的 Java 类(支持 XML 编组和分组)。在这种情况下, WSDL 文件直接转化为 Java 类,然后作为 Java 对象来管理,使用这种方式一个缺陷就是使客户程序代码庞大,臃肿,不好管理,增加了系统的复杂性。
WSDL4J简介——解析和收集来自 WSDL 的信息
WSDL4J是用来解析WSDL文件的技术,很多WEB服务的底层实现都用了该技术。
但在传统的WEB服务实现方案中,该技术作为底层实现被屏蔽。而我们的项目为了能够动态的调用异构平台的未知服务,必须使用该技术。
所以说WSDL4J 包将被用于以编程方式表示 WSDL 文件的元素,所以我可以浏览和收集来自该文件的各种信息。
在服务资源库中查找 Web 服务
为了动态地调用 Web 服务,必须知道一些基本信息,如此Web服务的WSDL文档的URL、Web服务的名称。
当服务消费者在同一种服务中,即搜索结果中选择一个后,可以根据服务ID,以及Vector totalservices获取一个Web服务对象,这个对象包含了有关远程Web服务的足够信息,注意是足够信息,当然有最起码的WSDL 文档的 URL。既然我知道了WSDL 实现的 URL,那我就可以继续用 WSDL4J 直接请求来自服务提供者的文档并对其进行解析,从而获得了下一步调用服务所需要的一个完全的Web服务信息,如操作的调用参数信息等等。
解析
WSDL
既然经过上面步骤我们拥有了用于 Web 服务的 WSDL文档的 URL,那么我们现在就可以用到WSDL4J来解析它了。为了使用 SAAJ构建SOAP消息调用该服务,我们将需要从 WSDL 收集下列最基本的信息:
目标名称空间
服务名称
端口名称
操作名称
操作输入参数
<
wsdl:definitions
xmlns:wsdl
="
http://schemas.xmlsoap.org/wsdl/
"
xmlns:soap11
="
http://schemas.xmlsoap.org/soap/envelope/
"
xmlns:soap12
="
http://www.w3.org/2003/05/soap-envelope
"
xmlns:soapenc11
="
http://schemas.xmlsoap.org/soap/encoding/
"
xmlns:soapenc12
="
http://www.w3.org/2003/05/soap-encoding
"
xmlns:tns
="
http://weather.cactus.org
"
xmlns:wsdlsoap
="
http://schemas.xmlsoap.org/wsdl/soap/
"
xmlns:xsd
="
http://www.w3.org/2001/XMLSchema
"
targetNamespace
="
http://weather.cactus.org
">
每个WSDL的根元素都是<definitions>,一般都在这里定义文档中的各种名称空间。对于上面的WSDL,定义了不少名称空间,现在来说说它们的作用。
我们都知道,WSDL应该是格式正确的XML文档。进一步,还应该把它看作一个Schema,因此,<definitions>元素中可以定义targetNamespace属性,表示在这个元素下的所有元素都属于这个目标名称空间。xmlns表示缺省的名称空间,请注意在上面的文档中,这个缺省名称空间的值和xmlns:wsdl的值是相同的(都是http://schemas.xmlsoap.org/wsdl/)。因此,在这个WSDL中的很多<wsdl:XXX>元素,例如<wsdl:types>、<wsdl:portType>等等,实际上省略掉前面的“wsdl:”效果也是一样的。
名称空间xmlns:tns, tns是This NameSpace的缩写,用来对当前WSDL进行引用。由于一个WSDL映射一个包(package),所以
我们在Java平台下基于XFire开发的一个天气Web服务
为我们生成的WSDL里,tns的值(
http://weather.cactus.org
)包含java包(org.cactus.weather)的信息就是顺理成章的了。请注意,tns1的值和<wsdl:types>里的<schema>元素的targetNamespace值是相同的。
名称空间xmlns:wsdlsoap是在与soap绑定时使用的,例如<wsdlsoap:binding>、<wsdlsoap:operation>等元素会用到。
名称空间xmlns:xsd是对XML Schema中各种数据类型的引用,例如string、boolean等等。想知道XML Schema中一共都定义了哪些数据类型,只要查看该名称空间的值(http://www.w3.org/2000/10/XMLSchema)即可。
在看具体的解析之前先看看WSDL4J的基本用法:
首先通过我们系统获取企业所发布服务的WSDL文档.一旦获取了服务的WSDL文档,就可以采用WSDL4J对其进行解析.为了使用Web服务调用框架进行服务的调用,需要从WSDL文档中进行以下信息的收集:目标名称空间;服务名称;端口名称;操作名称;输入输出参数.
WSDL文档的分类
WSDL文档主要分为4种样式:文档/文字、文档/编码、RPC/文字、RPC/编码。基于文档和RPC样式的WSDL文档在数据类型定义方面主要存在如下区别:
基于文档样式的WSDL文档的每个Message所包含的Part部分指向一个Schema元素声明;
基于RPC样式的WSDL文档的每个Message所包含的Part部分指向了Schema类型的定义.
不同文档样式的数据类型定义区别如下所示:
<s:element name="getQuote">
<s:complexType>
<s:sequence>
<s:element minOccurs="0"maxOccurs="1"name="symbol"type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
基于文档的表示:
<message name="getQuoteSoapIn">
<part name="parameters" element="s0:getQuote"/>
</message>
基于RPC的表示:
<message name="getQuoteSoapIn">
<part name="symbol"type="s:string"/>
</message>
用WSDL4J进行服务描述解析的基本流程
由于两种样式的WSDL文档在进行数据类型定义时不尽相同,因此采用WSDL4J在进行服务参数解析时也不相同,其中基于RPC样式的服务参数能够很好地被解析,而基于文档样式的服务参数需要采用其他如解析XML文档的方法去执行.文中应用采用基于RPC样式的服务描述文档,其中采用WSDL4J进行服务描述解析的代码框架见程序清单2:
1)获取服务的definitions根节点
WSDLFactory factory= WSDLFactory.newInstance();
WSDLReader reader=factory.newWSDLReader();
Def=reader.readWSDL(WsdlURL);
2)获取目标名称空间
targetNamespace=Def.getTargetNamespace();
3)获取服务端口
Vector allPorts=newVector();
Mapports= Def.getPortTypes();
…
PortType port= (PortType)allPorts.elementAt(0);
4)选择服务名称和端口名称
//首先选择和当前端口类型相同的绑定QName
QName bindingQName=null;
Mapbindings= Def.getBindings();
…
Binding binding= (Binding)bindings.get(it.next());
if(binding.getPortType()==port)
{bindingQName=binding.getQName();}
//然后通过端口绑定名称获取端口名称和服务名称
MapimplServices=implDef.getServices();
…
Serviceserv= (Service)implServices.get(it.next());
Mapm =serv.getPorts();
…
Portp= (Port)m.get(iter.next());
if(p.getBinding().getQName().toString().equals(bindingQName.toString())){
portName=serv.getQName().toString();
serviceName=p.getName();}
5)选择操作名称
Operationop= (Operation)operations.get(0);
operationName=op.getName();
6)保存输入参数名称和类型(输出参数类似)
Listparts=op.getInput().getMessage().getOrderedParts(null);
intcount=parts.size();
StringinNames=newString[count];
ClassinTypes=newClass[count];
for(inti=0;I<inNames.length;i++){
inNames[i]= (Part)parts.get(i).getName();
t = (Part)parts.get(i).getTypeName.
getLocalPart();
if("string".equals(t)
{inTypes[i]=String.class;…}
}
对于我们项目具体的解析过程
下面用几个代码片段来解释整个过程:
清单1 Transformation.java
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
清单1 主要的任务就是根据WSDL文档URL地址(serviceinfo参数只含有有限的信息,如ID,WSDL文档的URL),构建一个com.swc.se.domain.Service类,用来描述WSDL文件中的Service元素,即用来装载从Service元素和其子元素中解析出来的数据。同时,com.swc.se.domain.Service类也对应一个远程服务。
第一步:读取WSDL文档的根构建一个Definition 对象:
Definition def = reader.readWSDL(null, serviceinfo.getWsdllocation());
第二步:使用castor工具根据上一步生成的def对象,从Definition 的子元素types生成java对象wsdlTypes,它是一个向量vector:
wsdlTypes = createSchemaFromTypes(def);
第三步:获得在WSDL文档中定义的所有Service对象
Map services = def.getServices();
在这里做了一个约定,为了把问题简单化,只把WSDL文档看成是只含有一个service对象,当然了可以有多个service对象,因为在一个WSDL文档中,<service>的name属性用来区分不同的service,但是同一个service中可以有多个端口,它们也有"name"属性:
Iterator svcIter = services.values().iterator();
第四步:为找到的当前Service对象构建一个com.swc.se.domain.Service类
populateComponent(serviceinfo, (Service)svcIter.next());
而其实上面的好几步都是一个复杂的过程,所以分别用方法抽出来了,第二步从子元素types生成java对象wsdlTypes过程如清单2.
所以先看看第二步都有哪些自步骤:
清单2 Transformation.java
对于清单2,是为清单1的第二步服务的,过程如下:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
1.
保存types下的所有schema:Vector schemas=new Vector();
2.
获得Types元素的schema集合,schemaExtElem是Types元素的schema集合,
因为可能会有多个schema,其实在这里我们如果把问题再次简单化的话就可以看成是一个schema,返回的就是ExtensibilityElement了:
Vector
schemaExtElem= findExtensibilityElement(wsdlDefinition.getTypes().getExtensibilityElements(), "schema");
3.
对于2中的Schema集合,获得每个Schema:
ExtensibilityElement schemaElement=(ExtensibilityElement)schemaExtElem.elementAt(i);
schemaElementt= ((UnknownExtensibilityElement)schemaElement).getElement();
UnknownExtensibilityElement是用来封装任意的子元素,即一个Schema.
4.根据当前Schema所对应的对象(
org.w3c.dom.Element
):schemaElementt,返回一个标准的Java对象schema.
Schema schema=createschemafromtype(schemaElementt,wsdlDefinition);
而第4步其实也是一个复杂过程,如清单3。而最终要实现的就是:
这几个变换:<definitions>——< schema>——WSDL4J包的ExtensibilityElement ——org.w3c.dom.Element下的Element——org.exolab.castor.xml.schema.Schema的Schema
清单3 Transformation.java
清单3的一个任务就是实现这几个变换:<definitions>——< schema>——WSDL4J包的
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/7ff8d92cded7e0ce15e7ca1acc870052.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
ExtensibilityElement ——org.w3c.dom.Element类型的Element——org.jdom.Element类型
的Element——org.exolab.castor.xml.schema.Schema类型的Schema的最后一步:org.exolab.castor.xml.schema.Schema的Schema。
使用JDOM包import org.jdom.input.DOMBuilder把org.w3c.dom.Element类型的Element转化为org.jdom.Element类型的Element:
// 从DOM到JDOM的转换
DOMBuilder domBuilder = new DOMBuilder();
org.jdom.Element jdomSchemaElement = domBuilder.build(schemaElement);
这时候离目标org.exolab.castor.xml.schema.Schema的Schema。只有一步了:
schema = XMLSupport.convertElementToSchema(jdomSchemaElement);即,
通过XMLSupport类把一个JDOM类型的SchemaElemen转化为org.exolab.castor.xml.schema.Schema的Schema!具体过程就不再细说了。
还有一个任务就是:在传进来的实参Definition wsdlDefinition对象里获得definition元素
所有相关的命名空间:
Map namespaces = wsdlDefinition.getNamespaces();
if(namespaces != null && !namespaces.isEmpty()){
Iterator nsIter = namespaces.keySet().iterator();
while(nsIter.hasNext()){
String nsPrefix = (String)nsIter.next();
String nsURI = (String)namespaces.get(nsPrefix);
if(nsPrefix != null && nsPrefix.length() > 0) {
org.jdom.Namespace nsDecl = org.jdom.Namespace.getNamespace(nsPrefix, nsURI);
jdomSchemaElement.addNamespaceDeclaration(nsDecl);
}
}
}
其实以上说的清单2跟清单3用一句话来说就是:帮助清单1实现第二步:使用castor工具根据上一步生成的def对象,从Definition 的子元素types生成java对象wsdlTypes,它是一个向量vector:wsdlTypes = createSchemaFromTypes(def);。
收集这些wsdlTypes信息是为后面构造操作operation作铺垫的。
对于清单1中的
第四步:为找到的当前Service对象构建一个com.swc.se.domain.Service类,实现过程如下面清单4。
清单4 Transformation.java
private com.swc.se.domain.Service populateComponent(com.swc.se.domain.Service component, Service service)
{
QName qName = service.getQName();
String namespace = qName.getNamespaceURI();
String name = qName.getLocalPart();
component.setName(name);
Map ports = service.getPorts();
Iterator portIter = ports.values().iterator();
while(portIter.hasNext())
{
Port port = (Port)portIter.next();
Binding binding=port.getBinding();
List operations=buildOperations(binding);
Iterator operIter=operations.iterator();
while(operIter.hasNext())
{
com.swc.se.domain.Operation operation=(com.swc.se.domain.Operation)operIter.next();
Vector addrElems=findExtensibilityElement(port.getExtensibilityElements(), "address");
ExtensibilityElement element=(ExtensibilityElement)addrElems.elementAt(0);
if(element != null&&element instanceof SOAPAddress)
{
SOAPAddress soapAddr = (SOAPAddress)element;
operation.setTargetURL(soapAddr.getLocationURI());
}
component.addOperation(operation);
}
}
return component;
}
清单4代码是构建一个我们的对象:com.swc.se.domain.Service。代码很容易读懂,因为都是一些WSDLforJ的特殊API,即对应WSDL文档大部分元素的相对应的Java类。这个过程就不像上面那样分析了,因为道理是一样的。
提示:
按这样的思路:
1. 下对应WSDL文档的某个类A
WSDLforJ API
2.
调用类A的方法findExtensibilityElement(A.getExtensibilityElements());返回向量Vector
3.
获取其中一个ExtensibilityElement B;它对应的就是wsdl文档的某个标签<B>对应的类为BB
4.
if(B!= null && B instanceof BB)
{
BB bb = (BB)B;
….
}
……
我想暂时就先总结这么多吧,掌握了规律后我想就不难了,如果你坚持看到这里了,应该对WSDL4J搭配castor+jdom来解析WSDL文档有初步的认识了吧。肯定还有很多细节没有说到,以后再慢慢补吧.