使用 Axis2 和 JiBX 将 Java 类转换成 Web 服务,第 1 部分: 使用 XML 通过 Java 类定义 Web 服务

利用 XML 为 Web 服务部署重用 Java 代码

XML 功能强大,使用它能够定义任何事物。更重要的是,它是使大多数应用程序具有外部可读格式的基础,对于本系列文章所使用的 Axis2 和 JiBX 尤为显著。随着 Web 服务的日益普及,使用 Axis2 和 JiBX 将原来的 Java® 项目转换成功能全面的 Web 服务也显得格外紧迫。以往,Web 服务都是根据一个服务和一个单一的类自动生成的,而现在开发人员可以通过已有项目中的各种 Java 类生成一个或多个服务。本文(本系列的第 1 部分)使用 XML 通过已有 Java 类定义了一个 Web 服务。

Tyler Anderson (tyleranderson5@yahoo.com), 自由撰稿人, 自由职业者

Tyler Anderson 于 2004 年获得 Brigham Young 大学的计算机科学学士学位,并于 2005 年获得了该大学的电子及计算机工程硕士学位。他于 2005 年 5 月至 2006 年 8 月担任 Stexar Corp. 的设计工程师。Tyler 于 2005 年初被 Backstop Media LLC 发现,并已经为 IBM developerWorks 撰写了大量文章和教程,并编写了代码。



2007 年 5 月 10 日

简介

Web 服务在日常开发中重要性与日俱增,Axis2 也成为了倍受人们欢迎的开发 Web 服务的开放源码平台。Axis2 使用 Java 语言编写,它能利用了 JiBX(一种框架,用于将XML和Java绑定在一起)的自由性。假设您有一个含有大量 Java 类和数据结构的 Java 项目,而且不想打乱或者更改它们。JiBX 会帮助您实现这一切,它把在 Axis2 中使用的 XML 数据与 Java 类绑定在一起。这样做的好处是代码易于维护,因为 Web 服务只使用已经开发好、可靠、真正的 Java 类。

本文介绍了将在本系列中使用的 Java 类,并解释了如何生成能准确描述这些 Java 类的 Web 服务描述语言(Web Services Description Language,WSDL)和 JiBX 定义。本系列的第 2 部分将使用 WSDL 和 JiBX XML 文档创建一个 Web 服务的 Java 实现,该 Web 服务使用这个 Java 类作为数据绑定。


系统需求

要学习这个分为两部分的系列文章,需要如下软件:

  • Axis2,binary and WAR 版,可从 Axis2 主页下载(请参阅 参考资料)。
  • JiBX 1.1,可以从 JiBX SourceForge 页面下载(请参阅 参考资料)。
  • Geronimo 1.1.1,可以从 Geronimo 主页下载(请参阅 参考资料)。

下载完上述所有软件后,解压 Geronimo 并键入:java -jar <geronimo-home>/bin/server.jar

然后,为部署 axis2.war 文件,将 axis2 文件复制到 <geronimo-home>/deploy 目录。

解压 Axis2 二进制文件,将 AXIS2_HOME 环境变量设置为 Axis2 二进制文件解压的目录(本例中设置为 c:\apps\axis2-1.1)。然后解压 JiBX,并将 <jibx-home>/lib 目录的所有 JAR 文件(除了 stax-api.jar 文件之外,因为 Axis2 已经含有了 stax-api.jar 文件)复制到 <axis2-home>/lib 目录下。

这样就设置好了环境。


Java 类

这里提供了一些 Java 类,用于构成一个简单的 Web 服务 Java 项目。使用什么样的 Java 类并无大障,您也可以使用自己创建的 Java 类。本文使用的项目含有三个类:OneWayRequest 类、TwoWayRequest 类和 TwoWayResponse 类。按顺序看看每个类,我们先从 OneWayRequest 类开始(参见清单 1)。

清单 1. OneWayRequest Java 类
package com.ibm.devWorks.xml.simpleService;

public class OneWayRequest {
  protected String requestData;

  public String getRequestData() {
    return this.requestData;
  }

  public void setRequestData(String requestData) {
    this.requestData = requestData;
  }

}

上面的代码中只含有一个字段,即 requestData,它包含了请求的数据。该类有两个方法:一个用于设置字段值,另一个用于检索字段值。

接下来再看一看清单 2 中的 TwoWayRequest 类。

清单 2. TwoWayRequest Java 类
package com.ibm.devWorks.xml.simpleService;

public class TwoWayRequest {
  protected String echoString;
  protected boolean booolean;

  public boolean getBooolean() {
    return this.booolean;
  }

  public void setBooolean(boolean booolean) {
    this.booolean = booolean;
  }

  public String getEchoString() {
    return this.echoString;
  }

  public void setEchoString(String echoString) {
    this.echoString = echoString;
  }

}

这个类要稍长一点,它定义了两个字段:一个是 echoString,另一个是 booolean。与第一个类相同,该类为每个字段都定义了一个 getter 和一个 setter 方法。

清单 3 显示了最后一个类,即 TwoWayResponse 类。

清单 3. TwoWayResponse Java 类
package com.ibm.devWorks.xml.simpleService;

public class TwoWayResponse {
  protected String echoString;
  protected boolean invertedBoolean;

  public boolean getInvertedBoolean() {
    return this.invertedBoolean;
  }

  public void setInvertedBoolean(boolean invertedBoolean) {
    this.invertedBoolean = invertedBoolean;
  }

  public String getEchoString() {
    return this.echoString;
  }

  public void setEchoString(String echoString) {
    this.echoString = echoString;
  }

}

这个类与前一个 TwoWayRequest 类相当类似,不过这是没有必要的。响应类中可能会包含一项数据库记录中的一些数据项。这样,Java 类就完成了! 接下来,我们将介绍用于将这些类作为 Web 服务公开的 WSDL。


通过 WSDL 将 Java 类作为服务公开。

在本系统文章的第 2 部分中,我们将使用 Axis2 读取在本节中创建的 WSDL,用以创建 Web 服务的一个 Java 实现。

在深入学习之前,我们需要先了解一些关于 Web 服务的知识。OneWayRequest 类表示一个单向的 Web 服务操作,它只有一个请求,用于发送字段中的请求数据 requestDataTwoWayRequest 类和 TwoWayResponse 类表示一个双向的 Web 服务操作,它有一个请求和一个响应,响应中的 echoString 字段与请求中的 echoString 字段有着相同的值。响应中的 invertedBoolean 字段值与请求中的 invertedBoolean 字段值相反(如果请求中的 invertedBoolean 字段值为假,则响应中发送的 invertedBoolean 字段值为真)。

接下来回到 WSDL,我们首先需要建立名称空间,如清单 4 如示。

清单 4. 定义 WSDL 的名称空间。
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
   xmlns:apachesoap="http://xml.apache.org/xml-soap"
   xmlns:impl="http://ibm.com/developerWorks/xml/SimpleService"
   xmlns:intf="http://ibm.com/developerWorks/xml/SimpleService"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   targetNamespace="http://ibm.com/developerWorks/xml/SimpleService">
...

这基本上准备好了 WSDL,稍后我们将在 WSDL 中引用名称空间。当 Axis2 读取 WSDL 文件时,它需要知道我们引用的名称空间的值。

接下来,定义模式,如清单 5 所示。

清单 5. 定义模式
   targetNamespace="http://ibm.com/developerWorks/xml/SimpleService">
  <wsdl:types>
    <schema
       elementFormDefault="qualified"
       targetNamespace="http://ibm.com/developerWorks/xml/SimpleService"
       xmlns="http://www.w3.org/2001/XMLSchema">
      
      <!-- ELEMENTS -->
      
      <element name="OneWayRequest">
        <complexType>
          <sequence>
            <element name="requestData" type="xsd:string"/>
          </sequence>
        </complexType>
      </element>
      
      <element name="TwoWayRequest">
        <complexType>
          <sequence>
            <element name="echoString" type="xsd:string"/>
            <element name="booolean" type="xsd:boolean"/>
          </sequence>
        </complexType>
      </element>
      <element name="TwoWayResponse">
        <complexType>
          <sequence>
            <element name="echoString" type="xsd:string"/>
            <element name="invertedBoolean" type="xsd:boolean"/>
          </sequence>
        </complexType>
      </element>

    </schema>
  </wsdl:types>
...

您应该对此代码比较熟悉。这在本质上是通过模式定义的 Java 类。请注意,Java 类中的字段匹配上述模式元素中子元素。还需注意,名称空间为 http://ibm.com/developerWorks/xml/SimpleService,在您创建了 JiBX 定义描述之后将发现它的重要性。

此时再定义消息、端口类型、绑定和 WSDL 服务(如清单 6 所示)。

清单 6. 完成 WSDL 定义
...
  </wsdl:types>

  <!-- MESSAGES -->

  <wsdl:message name="OneWayRequestMessage">
    <wsdl:part name="input" element="impl:OneWayRequest"/>
  </wsdl:message>

  <wsdl:message name="TwoWayRequestMessage">
    <wsdl:part name="input" element="impl:TwoWayRequest"/>
  </wsdl:message>
  <wsdl:message name="TwoWayResponseMessage">
    <wsdl:part name="output" element="impl:TwoWayResponse"/>
  </wsdl:message>

  <!-- Port type (operations) -->

  <wsdl:portType name="SimpleServicePortType">

    <wsdl:operation name="OneWay" parameterOrder="input">
      <wsdl:input name="OneWayRequestMessage"
                  message="impl:OneWayRequestMessage"/>
    </wsdl:operation>

    <wsdl:operation name="TwoWay" parameterOrder="input">
      <wsdl:input name="TwoWayRequestMessage"
                  message="impl:TwoWayRequestMessage"/>
      <wsdl:output name="TwoWayResponseMessage"
                   message="impl:TwoWayResponseMessage"/>
    </wsdl:operation>

  </wsdl:portType>

  <!-- BINDING (bind operations) -->

  <wsdl:binding
     name="SimpleServiceSoapBinding"
     type="impl:SimpleServicePortType">
    <wsdlsoap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>

    <wsdl:operation name="OneWay">
      <wsdlsoap:operation soapAction="OneWay"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
    </wsdl:operation>

    <wsdl:operation name="TwoWay">
      <wsdlsoap:operation soapAction="TwoWay"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>

  <!-- SERVICE -->

  <wsdl:service name="SimpleService">
    <wsdl:port binding="impl:SimpleServiceSoapBinding"
               name="SimpleService">
      <wsdlsoap:address location="http://localhost:8080/axis2/services/SimpleService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

定义的消息映射到模式中的请求和响应元素,由端口类型定义使用,每项操作的输入和输出都映射一个消息。绑定部分在本质上映射一项 SOAP 操作,确切定义了绑定服务的协议和传输方法及其相关操作。最后,服务部分指定了可用服务,展示了每个服务的服务端点(可以访问到服务的 URL)。

这样便完成了该 Web 服务的定义。接下来,我们将把 XML 映射到 Java 类,以便在本系列的下一部分中使用 JiBX 进行数据绑定。


创建 JiBX 定义描述

JiBX 定义描述的主要目的是将 Java 类映射到名称空间,包括任何期望的字段。在看了本节创建的文件之后,您会将了解更多。首先,看一看 OneWayRequest 类是如何映射的(如清单 7 所示)。

清单 7. 映射 OneWayRequest Java 类
<?xml version="1.0" encoding="UTF-8"?>
<binding>
  <mapping name="OneWayRequest"
           class="com.ibm.devWorks.xml.simpleService.OneWayRequest">
    <namespace uri="http://ibm.com/developerWorks/xml/SimpleService"
               default="elements"/>
    <value name="requestData" field="requestData" usage="required"/>
  </mapping>
...

mapping 标签中的 name 属性指定了与 OneWayRequest 元素(位于清单 5 中创建的 WSDL 模式中)直接相关联的元素的名称。class 属性将元素与 Java 类映射起来,Java 类如 清单 1 所示。namespace 标签中的 uri 属性映射的名称空间为 http://ibm.com/developerWorks/xml/SimpleService,与清单 5 中 OneWayRequest 元素的名称空间是一样的。最后,能看到 requestData 子元素(位于 清单 5 中的 WSDL)是如何映射到 Java 类中的 requestData 字段(位于 清单 1 中的 value 标签)中的。name 属性指定了 WSDL 中的子元素,field 属性指定了 Java 类中的字段名称。

接下来,我们将介绍其它两个 Java 类是如何映射的,如清单 8 所示。

清单 8. 映射 TwoWayRequestTwoWayResponse Java 类
...
  <mapping name="TwoWayRequest" 
           class="com.ibm.devWorks.xml.simpleService.TwoWayRequest">
    <namespace uri="http://ibm.com/developerWorks/xml/SimpleService" 
               default="elements"/>
    <value name="echoString" field="echoString" usage="required"/>
    <value name="booolean" field="booolean" usage="required"/>
  </mapping>
  <mapping name="TwoWayResponse" 
           class="com.ibm.devWorks.xml.simpleService.TwoWayResponse">
    <namespace uri="http://ibm.com/developerWorks/xml/SimpleService" 
               default="elements"/>
    <value name="echoString" field="echoString" usage="required"/>
    <value name="invertedBoolean" field="invertedBoolean" 
           usage="required"/>
  </mapping>
</binding>

清单 8中,我们能看到 OneWayRequest 类、TwoWayRequest 类和 TwoWayResponse 类映射的相似之处。但是,此处的名称、类和字段指向的是 TwoWayRequestTwoWayResponse 元素的适当的数据。然而,不同之处之一就是这两个元素含有两个子元素或者字段。如果 mapping 标签没有子元素,则不会有 value 标签。如果 mapping 标签有多个子元素,那么 value 标签将相继列出,如清单 8 所示。


结束语

太棒了!我们已经完成了一半。我们利用了已有的 Java 类,为其定义了一个 XML 模式,并通过 WSDL 和 Web 服务中的操作将它们公开。我们创建了一个 JiBX 定义描述,它将 Java 类与模式中的元素映射起来,使 Axis2 JiBX 数据绑定能正确地将 Web 服务 SOAP 数据与 Java 类绑定在一起。

在第 2 部分中,Axis2 将使用 JiBX 定义描述生成服务主干和客户端的雏形。我们将在 Apache Geronimo 上部署最终的 Apache Axis2 Web 服务,然后生成并创建一个与部署好的 Web 服务通信的客户机,以此完成测试。


下载

描述名字大小
第 1 部分示例代码x-jibx1-source.zip3KB

参考资料

学习

  • 您可以参阅本文在 developerWorks 全球网站上的 英文原文
  • JiBX 主页: 了解更多有关在 SourceForge 项目中使用 JiBX 框架绑定 XML 数据与 Java 对象的知识。
  • XML 和 Java 技术:数据绑定,第 3 部分: JiBX 体系结构(Dennis Sosnoski,developerWorks,2003 年 7 月):在这篇文章中学习更多有关 JiBX 架构的知识,以及如何使用其极佳的性能和巨大的灵活性将 XML 与 Java 对象映射起来。
  • Apache Axis2 主页:学习 Axis2 和 JiBX 是如何被整合到 Axis2 1.1 中去。
  • JiBX:从 Axis2 主页获取更多有关 JiBX 的信息。
  • Axis2: 在 Axis2 主页学习、参与讨论、下载和发表想法。
  • Web 服务与 Axis2 体系结构(Eran Chinthaka,developerWorks,2007 年 2 月):获取更多有关 Axis2 架构和 Web 服务的知识。Axis2 是模块化、可扩展的,通过这篇文章了解它为什么能成为下一代的 Web 服务平台。
  • developerWork 中国网站 XML 专区:了解 XML 的方方面面。
  • IBM XML 认证:看看如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。
  • XML 技术文档库:developerWorks XML 专区提供了大量技术文章和提示、教程、标准以及 IBM 红皮书。
  • developerWorks 技术活动网络广播:随时关注技术的最新进展。

获得产品和技术

  • Apache Axis2:下载 Web 服务的核心引擎。
  • JiBX 1.1:下载用于将 XML 数据与 Java 绑定在一起的 JiBX 框架。
  • Geronimo 1.1.1:获取这个易于使用、开放源码的服务器。
  • JiBXSoap:在 JiBX 主页中看看 JiBX 的一个 SOAP Web 服务实现。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML, Java technology, SOA and web services, Open source
ArticleID=219240
ArticleTitle=使用 Axis2 和 JiBX 将 Java 类转换成 Web 服务,第 1 部分: 使用 XML 通过 Java 类定义 Web 服务
publish-date=05102007