中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> Bea专区 > BEA Workshop
Workshop 8.1中的Web服务: XML阻抗匹配
作者:Jon Mountjoy 时间:2006-08-04 12:40 出处:bea.com.cn 责编:月夜寒箫
              摘要:Workshop 8.1中的Web服务: XML阻抗匹配
创建web服务时,开发人员通常会从现有的WSDL、现有的实现或者以上二者的组合开始。在本文中,我们分析了WebLogic Workshop 8.1的一些功能,这些功能可以使这些web服务变得健壮,从而无惧WSDL或实现数据类型中的变化。在这个过程中,我们还注意到WebLogic Workshop和它生成的工件之间的交互,比如带注释的web服务文件。

  本文在给定一些WSDL、一个实现类或者以上二者的一些组合的情况下,考虑了您可以在一个简单的web服务中融入灵活性的各种方式。例如,您可以从特定的WSDL和已有的一些种类的实现开始。您如何按照WSDL中指定的那样,把传入的数据映射为您的实现中的参数呢?有一个好机会,即WSDL中定义的数据类型和您的实现中的数据类型不匹配。从不同的角度来看,或许您有一个既定的web服务实现,但是现在有客户端想要您支持一个略有不同的WSDL接口(也许是一个更新的版本)。第一感觉可能是重写实现,或者可能的话,修改WSDL——但是上述两种方法都无法令人满意。
  重写实现可能会影响系统的其他部分,而且它会给编码人员增加很多负担。如果WSDL再次以一种保持数据但是修改所使用的XML架构的方式变化,那又该如何呢?您将不得不再次修改您的实现。另一个选择是修改WSDL,但这种方法也不总是可用——尤其是当已经建立并使用web服务时。
  WebLogic Workshop提供几种方法实现WSDL和实现之间的阻抗匹配。它有效地使用了一种功能强大的转换机制,用于在从客户端接收到的XML和您的实现所使用的XML之间进行转换。它为web服务返回的XML提供同样的功能。这使得您的接口和实现更加不容易变化,而且灵活的多。本文对这些机制进行了剖析。它假定您已经具有XMLBeans、 XML架构和WSDL方面的知识。
  本文中列举的例子显示了Workshop生成的所有文件,并证明了这种灵活性仍然可以使开发人员完全控制web服务代码。本文末尾提供了用于下载所有代码的连接。

考虑创建Web服务
  创建我们感兴趣的web服务的两个方面是到web服务本身的接口(通常在WSDL中指定),和您想要关联到web服务接口的业务逻辑。根据您已经建立的是WSDL还是实现,您可以采取4种方法:

 

  • 已建立WSDL,当前无实现——在这里,您已经有了描述服务的WSDL,而且您需要创建web服务。WebLogic Workshop让您可以直接从WSDL简单地创建web服务实现。WebLogic Workshop还可以自动生成必要的类型,当然,接口和实现之间将会有几近完美的映射。
  • 无现有实现或WSDL——假定您需要创建web服务来公开一些数据,而且你既没有实现,也没有WSDL。在这种情况下,您只要首先创建它们,然后遵照其他方法之一即可。Workshop推荐的方法是创建用于描述您想要在公共接口中公开的数据的XML架构类型,并且在您的实现中使用这些类型。然后,Workshop可以为您自动生成WSDL,以及使用并公开这些类型的web服务。
  • 已建立实现,无WSDL——这里,您有您想要公开的web服务的现有实现,但是对WSDL没有约束。正如我们将看到的那样,Workshop可以自动公开参数,并执行在方法中使用的参数和(新的)WSDL中定义的类型之间的必要类型映射。Workshop创建XML映射,该图可将您的实现的数据类型映射为可以用在WSDL中的XML架构。当确定您想要在WSDL接口中公开的确切类型时,这些XML映射可以提供很大程度上的灵活性。
  • 已建立WSDL,且有现有实现——假定您有一个预定义的WSDL和一些已经写好的业务逻辑,而且WSDL中公开的数据类型和实现的数据类型不匹配。这种情况通常出现在WSDL接口以某种方式变化时。Workshop提供XQuery来填补这条鸿沟。这种机制可以把传入消息中的数据映射为实现中使用的类型,而且反之亦然。

  本文的余下部分对这每一个用例都进行了分析。注意,我们没有把重点放在Workshop提供的许多其他web服务功能上。例如,我们没有说明如何添加缓冲、回调或web服务会话,我们也没有指出在创建与其他控件交互的web服务控件过程中的灵活性。

已建立WSDL,无实现
  让我们考虑第一种情况:我们有一份描述某个web服务的WSDL文档,而且我们想实现该web服务。正如您将看到的那样,这很容易做到。清单1显示了我们将要使用的WSDL。

清单1.Established.wsdl
<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:tns="http://www.openuri.org/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   targetNamespace="http://www.openuri.org/">
  
  <types>
   <xsd:schema elementFormDefault="qualified"
       targetNamespace="http://www.openuri.org/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:art="http://www.oreilly.com/2004/articles">
     <xsd:element name="myMethod">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:element ref="art:myarticle"/>
           <xsd:element name="value" type="s:int"/>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
      <xsd:element name="myMethodResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="myMethodResult" type="s:string" minOccurs="0"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
    <xs:schema elementFormDefault="qualified"
      targetNamespace="http://www.oreilly.com/2004/articles"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:articles="http://www.oreilly.com/2004/articles">
      <xs:element name="myarticle">
        <xs:complexType>
          <xs:sequence>
            <xs:element ref="articles:myid"/>
            <xs:element ref="articles:title"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="myid" type="xs:ID"/>
      <xs:element name="title" type="xs:string"/>
    </xs:schema>
  </types>
 
  <message name="myMethodSoapIn">
    <part name="parameters" element="tns:myMethod"/>
  </message>
  <message name="myMethodSoapOut">
    <part name="parameters" element="tns:myMethodResponse"/>
  </message>
  <portType name="MyServiceSoap">
    <operation name="myMethod">
      <input message="tns:myMethodSoapIn"/>
      <output message="tns:myMethodSoapOut"/>
    </operation>
  </portType>
  <binding name="MyServiceSoap" type="tns:MyServiceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <operation name="myMethod">
      <soap:operation soapAction="http://www.openuri.org/myMethod" style="document"/>
      <input> <soap:body use="literal"/> </input>
      <output> <soap:body use="literal"/> </output>
    </operation>
  </binding>
  <service name="MyService">
    <port name="MyServiceSoap" binding="tns:MyServiceSoap">
      <soap:address location="http://localhost:7001/MyWSProject/MyWS/MyService.jws"/>
    </port>
  </service>
</definitions>

  这里,我们想要重点讨论的关键元素是,WSDL定义了一个描述web服务的输入和输出的类型架构。实现一个满足这种WSDL条件的web服务的基本方法如下:

  • 把WSDL文件导入到一个web服务项目中。
  • 在Schemas项目中放上一份它的拷贝。这将生成映射到架构的XMLBeans,我们稍后可以使用它。
  • 右键单击web服务项目中的WSDL文件,然后选择“Generate Web Service”。然后,您将看到一个对话框,内容是存在匹配的XMLBean并询问是否要使用它们。点击“Yes”。

  这将生成一个Java Web Services (JWS)文件,它在WebLogic Workshop中的扩展名为.jws。至此,您可以运行应用程序,这将编译生成的XMLBeans,部署web应用程序,并在您的浏览器中打开Workshop测试控制台。清单2显示了一些这种生成的文件的内容。

清单 2. 生成的Java Web Services文件

/**
 * :wsdl file="#MyServiceWsdl"
 * -info:link autogen-style="xmlbean" source="Established.wsdl" autogen="true"
 */
public class Established implements com.bea.jws.WebService
{
   
    /**
     * :operation
     * :protocol form-post="false" form-get="false"
     */
    public java.lang.String myMethod (com.oreilly.x2004.articles.MyarticleDocument myarticle, int value)
    {
        // place your code here
          return myarticle.getMyarticle().getTitle();
    }
 
    static final long serialVersionUID = 1L;
}
  这是一个简单的以元数据表示的POJO实现文件。方法的第一个参数具有和WSDL中定义的类型相应的生成XMLBean类型。测试环境让您输入您想要传递给方法的XML,这样在这个例子中,我们可以使用下面的文档:

<myMethod xmlns="http://www.openuri.org/" xmlns:art="http://www.oreilly.com/2004/articles">
  <art:myarticle>
    <art:myid>string</art:myid>
    <art:title>string</art:title>
  </art:myarticle>
  <value>3</value>
</myMethod>

  使输入和输出映射为XMLBeans有很多好处。开发转向变得很快(我们只要把WSDL文件放入Schema项目中即可),而且您可以立即访问传入文档的所有部分。这里的关键所在是,WSDL中使用的架构直接对应于实现中使用的XMLBean类型。这里出现了一个问题,即在不用编写复杂的映射代码的情况下,如何处理WSDL或我们在实现中使用的XMLBean出现变化的情形。稍后我们将给出这个问题的答案。

无已建立的WSDL或实现
  如果没有准备好的稳定WSDL或实现接口,我们自己可以自由地定义这一切。开始的最快方法是定义我们想要在web服务接口中公开的任何复杂类型。这项工作应该使用标准的XML架构来完成。我们支持使用XMLBean方法,因为这种方法可以在后面以XQuery图的形式提供灵活性,本文稍后将给出相应描述。

清单 3. 架构NWNIArticle.xsd示例
<?xml version="1.0"?>
<xs:schema
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          xmlns:tns="http://www.oreilly.com/2004/articles2"
          targetNamespace="http://www.oreilly.com/2004/articles2"
          elementFormDefault="qualified"
          attributeFormDefault="unqualified">
   
    <xs:element name="myarticle2">
        <xs:complexType>
          <xs:sequence>
            <xs:element ref="tns:myid"/>
            <xs:element ref="tns:title"/>
          </xs:sequence>
         </xs:complexType>
      </xs:element>
      <xs:element name="myid" type="xs:ID"/>
      <xs:element name="title" type="xs:string"/>  
</xs:schema>

  清单3显示了这样一个示例架构。注意,它和清单1 WSDL中定义的架构稍微有些不同。它还有一个不同的命名空间。您有了架构之后,将其放入Schema文件夹中,然后它会生成相应的XMLBean。
  要创建web服务,遵照使用WebLogic Workshop的项目中的通常步骤:

  • 右键单击项目,然后选择"New",然后选择"Web Service"。这将生成一个空白的JWS文件,我把它命名为NoWSDLNoImpl.jws。
  • 使用图形视图,创建一个名为"myMethod"的方法。单击它可以查看源代码视图,您可以在源代码视图中修改方法的签名。

  对于这个例子来说,我已经把方法的签名修改为使用我们刚刚定义的XMLBean类型:

import com.oreilly.x2004.articles2.Myarticle2Document;
 /**
  * :operation
  */
 public String myMethod2(Myarticle2Document doc, int value) {
   return doc.getMyarticle2().getTitle();
 }

  我们再次以与实现中的相应XMLBean匹配的WSDL中描述的类型作为结束。下面的两节对这一点进行了扩展,具体是通过分析如果正好相反,我们想要在与WSDL中的架构无简单对应关系的实现中公开类型(使用XML映射),或者如果出于某些原因,我们想要修改定义在WSDL中的接口类型(使用XQuery),我们要做些什么。

无已建立的WSDL和已建立的实现
  现在,让我们分析这样一种情况,即您有(假定为)Java控件形式(或封装在Java控件中)的业务逻辑,而且您想把它们公开为web服务。例如,我们可能有像下面这样的方法(当然,在实际的实现中,业务方法的功能更加复杂,比如调用其他控件):

public int businessMethod(int value, String artName) {
return value * 2;
}

  既然我们想要给出一种没有使用XMLBean的方法(前面的各节说明了如何使用XMLBean来做到这一点),我们选择了在参数中使用简单的Java类型。把它公开为web服务最简单的方法是,右键单击Java控件,然后选择"Generate Test JWS (Stateless)"。结果将生成一个仅仅使用Java控件中的业务逻辑的JWS文件:

package MyControl;
 
/**
 * -info:link autogen-style="stateless" source="MyBusinessImpl.jcs" autogen="true"
 */
public class MyBusinessTest implements com.bea.jws.WebService
{
    static final long serialVersionUID = 1L;
 
    /** :control */
    public MyControl.MyBusiness myBusiness;
 
    /** :operation
     */
    public int businessMethod(int value, java.lang.String artName)
    { return myBusiness.businessMethod(value, artName); }
 
}

  现在,我们将要考虑的是如何操纵将被公开给客户端的WSDL。如果您想要了解Workshop为JWS文件指派了哪个WSDL,您可以右键单击该文件,然后选择"Generate WSDL File"。Workshop自动创建WSDL和描述输入参数(和返回值)的架构,而且它会把该架构映射为参数(和返回值)。例如,下面给出了用于调用我们的业务方法的合法输入:

<businessMethod xmlns="http://www.openuri.org/">
 <value>3</value>
 <!--Optional:-->
 <artName>string</artName>
</businessMethod>

  为了创建这个,WebLogic Workshop事实上使用了一组默认的XML映射把SOAP体中的传入XML映射为业务方法的参数。(在本节的余下部分中,我们只讨论参数,但是XML映射也可以应用于返回值。)您还可以创建定制的XML映射;这可以使您有效地控制Workshop如何把传入SOAP消息中的XML映射为Java参数。正如您将看到的那样,这还可以为您提供一个机会修改您的web服务,以处理不同的SOAP消息,而无需修改实现。如果我们不喜欢这些映射,或者如果我们考虑到未来的变化,我们可以自己改进它们。
  如果您选择JWS文件中的业务方法,您将看到Property Editor在"parameter-xml"部分的下面有一个"xml map"项。选中此项将出现"Edit Maps and Interfaces"对话框,其上显示默认的XML映射,并为您提供修改它们的机会。图1显示了当前例子的结果。


图 1.默认的 XML映射

  XML映射为选择XML文档中的数据提供了一种非常直观的方式。在图1中,大括号中的名称与我们实现中的参数相对应。被传递给参数时,它们在XML上下文中的位置决定了数据的来源。例如,值参数将从"value"元素中的文本获得它的值,该元素本身应该位于"businessMethod"元素中,等等。
那么,让我们看看如何使用这些映射。假定,我们想给元素取不同的名称,而把值定义为一个属性而不是一个元素。(换一种说法,假定WSDL被修改,这样传入的XML就不一样了。)接着,我们可以简单地把XML映射修改为下面这样:

<businessMethod xmlns="http://www.openuri.org/"
  <articleDetails value="{value}">
    <name>{artName}</name>
  </articleDetails>
</businessMethod>

  实际上,您正以一种十分有趣的方式修改WSDL。通过简单地指定XML的形状,WebLogic Workshop断定WSDL是必需的,并在您的方法之前添加了一个转换层。所以对于这个例子,如果您为JWS生成WSDL,您将看到如下内容:

<s:element name="businessMethod">
  <s:complexType>
    <s:sequence>
      <s:element name="articleDetails">
        <s:complexType>
          <s:sequence>
            <s:element name="name" type="s:string"/>
          </s:sequence>
          <s:attribute name="value" type="s:int"/>
        </s:complexType>
      </s:element>
    </s:sequence>
  </s:complexType>
</s:element>

  这是修改您的web服务的一种强大手段,根本不用花费什么力气。XML映射本身作为JWS文件的另一个属性而结束,查看源代码时您可以查看这个属性。
  XML映射提供的转换系统比我们刚刚看到的还要丰富得多。例如,它们可以处理重复性元素,把它们映射为数组值。还有用于指定映射的纯XML语法。这对于从一些其他数据自动生成映射相当有用。您还可以把XML映射放在文件中;这允许您构建一个可重用转换的库。最后,您可以使用ECMAScript (JavaScript)的扩展版本,通过编程来修改定义Java参数的XML消息组件。为了很好地概览这些功能,请参考文章如何使用XML映射,或者查看WebLogic Workshop的优秀文档。

已建立的WSDL和已建立的实现
  在最后一个场景中,我们有一个已经建立的web服务接口(我们有描述服务的WSDL)和一个已经建立的实现(使用XMLBean),而该实现并不十分适合该web服务接口。注意,如果我们只是映射为标准的Java类型,而不是XMLBean参数,那么我们可以使用前面描述过的XML映射。
  作为一个示例实现,这里给出了一个带两个参数的简单Java控件。第一个参数是由XMLBean(映射为清单3中描述的架构)定义的,而第二个参数是double类型的。

package Control;
 
import com.bea.control.*;
import com.oreilly.x2004.articles2.Myarticle2Document;
/**
 * -info:code-gen control-interface="true"
 */
public class SimpleImpl implements Simple, ControlSource
{
    static final long serialVersionUID = 1L;
 
    /**
     * :operation
     */
    public String businessMethod(Myarticle2Document ad, double value)
    {
        return ad.getMyarticle2().getTitle();
    }
}

  我们试着设定这样一种场景,即我们有一个不兼容的WSDL。这里的关键在于,我们准备使用WebLogic Workshop在传入SOAP消息和实现之间插入一个转换器。所以,一天过去之后,我们在Java Web Service文件中公开的业务方法将和上面的Java控件拥有相同的签名。然而,我们将把传入类型声明为不同的类型,并构建一个转换器来匹配二者。举一个例子,让我们假定WSDL声明输入的参数以遵从这些架构:

<xs:schema elementFormDefault="qualified"
  targetNamespace="http://www.oreilly.com/2004/articles3"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:articles="http://www.oreilly.com/2004/articles3">
  <xs:element name="article">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="articles:title"/>
        <xs:element minOccurs="0" ref="articles:prices"/>
      </xs:sequence>
      <xs:attributeGroup ref="articles:article.attlist"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="description" type="xs:string"/>
  <xs:attributeGroup name="article.attlist">
    <xs:attribute name="id" use="required" type="xs:ID"/>
  </xs:attributeGroup>
  <xs:element name="title" type="xs:string"/>
  <xs:element name="prices">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="articles:price"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="price" type="xs:string"/>
</xs:schema>

  和示例文件中的EstablishedAndImpl.xsd一样,这个架构是可用的。如果我们的WSDL声明了这种类型的方法,那么一旦我们生成JWS文件,就会出现问题。除了属于不同的命名空间之外,该类型还声明了一系列“price”元素。当前,正如WSDL定义的那样,有效输入看起来应该是这样:

<ns0:article   
     xmlns:ns0="http://www.oreilly.com/2004/articles3"
     id="myId">
    <ns0:title>title_1</ns0:title>
    <ns0:prices>
        <ns0:price>11</ns0:price>
        <ns0:price>12</ns0:price>
    </ns0:prices>
</ns0:article>

  这里的思路是,我们想把title 元素和id 属性映射为Myarticle2Document 的title元素和id 属性(提供第一个参数给我们的业务方法),而且为了达到有趣的效果,我们准备计算"price"元素的总数,以便提供业务方法的第二个参数。
  根据您创建JWS文件的方式,您可能想稳定地建立上面的架构,作为方法输入的架构。为此,选择JWS文件中的方法,然后在Property Editor中的"parameter-xml"下选择"schema-element"项。在"Parameter"选项卡下,选择"Choose",您现在能够导航到WebLogic Workshop所知的任何架构元素。从EstablishedAndImpl.xsd选择"article"。
  现在,我们要做的是把这份文档映射为我们的Myarticle2Document类型,而且在此映射过程中,我们想把title元素复制给新的title元素,把id属性复制给一个id元素,然后计算price元素的总数,以便创建实现的第二个参数。
  再次选择方法,然后在Property Editor中从"parameter-xml"选择"xquery"。您将会看到XQuery Mapper,它为把使用XQuery把一份XML文档映射为另一份XML文档提供了一种有效的图形化方式。


图 2. XQuery Mapper外观

  左侧的Source架构描述了WSDL中声明的架构,而右侧的Target架构描述了参数。使用这个工具十分容易。我们只要把id属性拖拉到myid元素,然后再把title属性拖拉到title元素即可。我们还要把price元素(可能有很多)拖拉到值参数(记住这应该是一个double类型的值)。为了使这个总数等于price元素的值,我们打开"Advanced Option"面板,然后声明一个应该应用于转换的函数。在这个例子中,它是一个非常简单的XQuery片段 "xf:sum(/ns0:prices/ns0:price)",用于在适当节点上执行求和功能。
  XQuery Mapper的结果是一个简单的XQuery片段,作为JWS文件中的方法注释。它看起来是这个样子:

:parameter-xml xquery::
 declare namespace ns0 = "http://www.oreilly.com/2004/articles3"
 declare namespace ns1 = "http://www.openuri.org/"
 declare namespace ns2 = "http://www.oreilly.com/2004/articles2"
 
 <ns1:businessMethod>
     <ns2:myarticle2>
         <ns2:myid>{ data(/) }</ns2:myid>
         <ns2:title>{ data(/ns0:title) }</ns2:title>
     </ns2:myarticle2>
     <ns1:value>{ xf:sum(/ns0:prices/ns0:price) }</ns1:value>
 </ns1:businessMethod>
 ::

  这种简单性似乎与它提供给您的强大功能不合。只要拖拉几下鼠标按钮,您就能够使用XQuery的所有功能完全转换传入的XML。您还可以创建您可以在转换期间调用的XQuery代码片段,再次构建一个可重用转换的库,这类似于使用XML映射时所做的工作。参见“附加阅读”中列出的参考文章,以便获得关于XQuery更加详细的信息。

结束语
  WebLogic Workshop 8.1在创建web服务的过程中提供大量帮助。本文已经考察了其支持的一小部分——即创建简单的web服务、WSDL和XMLBean——重点放在这些功能如何交互,以提供能够应付变化的健壮的web服务实现。用于提供这种健壮性的三个首要机制是XMLBean、 XML映射和XQuery映射。
  XML映射提供一种直观的方式把传入的XML消息映射为Java参数。这允许公共接口中出现变化,而不会影响到实现。另一方面,XQuery映射为不同XML架构之间的映射提供了一种功能更加强大的转换语言。和XMLBean提供的极致抽象一起,这两种机制都做到了一点,即把修改web服务之后所需的编码工作量减到最低。

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有