posts - 495,comments - 227,trackbacks - 0

公开 Web 服务:WSDL

在线银行服务由几种操作构成,在实现这些操作之前,我们将首先介绍一下各操作。您将了解到各操作的细节、消息、端口类型和 WSDL 绑定。

操作

之前已经看到了 在线银行 Web 服务的概述。现在将了解构建此 Web 服务所需的操作:

Login

  • 登录允许您通过 Web 服务验证您的凭证,并获取一个令牌(token),证明您已通过验证,可进一步进行 Web 服务请求。
  • 传递两段数据(用户名和密码),返回一段数据(二进制令牌)。

Logout

  • 注销操作将从 Web 服务的经过身份验证的令牌/用户名列表中删除您的令牌和用户名。
  • 注销仅需您发送令牌,随后会返回一个确定布尔变量作为响应。

LookupAccounts

  • 查找您的账户信息。
  • 仅需令牌,返回账户号、类型和余额列表。

LookupTransactions

  • 按日期查找交易。
  • 发送令牌和账户号,以及可选日期范围(日期 1 和日期 2),回发一个交易复型数组作为响应(minOccurs="0" maxOccurs="unbounded")。

SearchTransactions

  • 按支票号或金额查找交易。
  • 允许更为复杂的交易搜索:传递账户号、令牌,以及支票号范围或金额范围,随后会返回一个满足条件的交易复型数组作为响应。

TransferFunds

  • 将资金从一个账户划拨到另外一个账户中。
  • 划拨资金操作要求您发送令牌、源账户、目标账户号和金额。回发一个确认布尔变量作为响应。

LookupPayees

  • 查看与您的在线账户相关的收款方。
  • 发送令牌,您将接收一个作为响应的收款方别名数组。

AddPayee

  • 向您的在线账户添加收款方。
  • 发送令牌和收款方复型,然后发送一个布尔确认信息作为响应。

EditPayee

  • AddPayee 基本完全相同,惟一的差异就是更新收款方而非将其插入基础数据库。

ViewPayee

  • 查看您的账户中与一个收款方相关的所有信息。
  • 发送令牌和收款方别名,检索收款方复型作为响应。

MakeBillPayment

  • 支付与一个收款方相关的一份账单。
  • 发送 BillPayment 复型和令牌,回发一个确认布尔变量作为响应。

ChangeBillPayment

  • 更改事先安排好的支付。
  • MakeBillPayment 基本相同,惟一的差异就是更新支付而非将其插入基本数据库。

LookupPendingPayments

  • 查看所有待定支付。
  • 仅发送令牌,您将接收一个 BillPayment 复型数组作为响应。

SubmitLoanApplication

  • 提交一份贷款申请表。
  • 发送 LoanApplication 复型和令牌,回发一个确认布尔变量作为响应。

ViewLoanApplicationStatus

  • 查看与您的在线账户相关的所有贷款状态。
  • 仅发送令牌,您将接收一个 LoanApplicationStatus 复型数组。

上边给出了全部定义。切记,有极多的操作要定义,并且不能过于繁冗或令人感到厌烦。因此,如果您遇到麻烦,可参考本教程后文 下载 一节中给出的 WSDL 文件,将其与上述操作比较。但下面我们会从始至终地详细介绍部分操作,作为示例供您参考,您可通过这些示例掌握如何处理其他操作。

接下来将定义 WSDL 文件的名称空间。





回页首


名称空间

尽管最初看上去有些古怪,但您的 WSDL 文件的名称空间相当重要,因为它们定义了整个 WSDL 中各标记(tag)的上下文。将以下代码放在已添加到 OnlineBanking.wsdl 文件中的数据结构之前,如 清单 7 所示。



清单 7. 设置 WSDL
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
   name="OnlineBanking"
   targetNamespace=http://www.example.com/OnlineBanking
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:tns="http://www.example.com/OnlineBanking"
   xmlns:xsd1="http://www.example.com/OnlineBanking/xsd"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

  <!-- Types -->
  <wsdl:types>
    <xsd:schema
       targetNamespace="http://www.example.com/OnlineBanking/xsd"
       xmlns="http://www.w3.org/2001/XMLSchema"
       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
       elementFormDefault="qualified">

xsd1: 名称空间指定 <xsd:schema 标记中定义的所有结构都属于 xsd1: 名称空间 (http://www.example.com/OnlineBanking/xsd),且需要据其引用,与 清单 6 中所引用的 RecurringBillPayment 复型类似。tnstargetNamespace 表示顶级 WSDL (http://www.example.com/OnlineBanking) 中定义的所有消息。接下来将为请求和响应定义元素标记。





回页首


请求

本节的剩余内容将引领您为 LoginLookupTransactions 操作创建 WSDL。请求为发送至 Web 服务的 SOAP 对象,可包含不同的内部层次结构,如前文中创建的数据结构。在 RecurringBillPayment 复型之后定义登录请求,如 清单 8 所示。



清单 8. 登录请求
      <xsd:element name="Login">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1"
                         name="username" type="xsd:string" />
            <xsd:element minOccurs="1" maxOccurs="1"
                         name="password" type="xsd: string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

本元素中恰好发送了一个用户名和密码。就是这样。接着定义查找交易元素,如 清单 9 所示。



清单 9. 查找交易请求
      <xsd:element name="LookupTransactions">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1"
                         name="accountNumber" type="xsd:int" />
            <xsd:element minOccurs="0" maxOccurs="1"
                         name="date1" type="xsd:date" />
            <xsd:element minOccurs="0" maxOccurs="1"
                         name="date2" type="xsd:date" />
            <xsd:element minOccurs="1" maxOccurs="1"
                         name="token" type="xsd:base64Binary" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

这里有一个接受 accountNumbertokenbase64Binary 类型)的查找交易请求。在后文中您将看到 base64Binary 类型在 Java 编程语言中转换为 byte[]。下面定义响应。





回页首


响应

客户机创建并发送请求。Web 服务接收请求并根据请求创建响应。定义登录响应,如 清单 10 所示。



清单 10. 登录响应
      <xsd:element name="LoginResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="1" maxOccurs="1"
                         name="valid" type="xsd:boolean" />
            <xsd:element minOccurs="1" maxOccurs="1"
                         name="token" type="xsd:base64Binary" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

登录成功响应给出有效变量的 true 值及令牌变量中的二进制令牌。再看看查找交易响应。按 清单 11 定义该响应。



清单 11. 查找交易响应
      <xsd:element name="LookupTransactionsResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element minOccurs="0" maxOccurs="unbounded"
                         name="transactions" type="xsd1:Transaction" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

该响应返回一个交易元素数组。注意此处使用的 xsd1: 名称空间。您只需直接为数组类型引用 清单 1 中定义的 Transaction 复型即可。接下来介绍消息。





回页首


消息

消息将发送给 Web 服务并返回,这些消息包括 SOAP 请求之前您在 响应 一节中定义的响应。定义 Login 请求和响应消息,如 清单 12 所示。



清单 12. 登录请求和响应消息
  <!-- Messages -->
  <wsdl:message name="Login">
    <wsdl:part name="parameters" element="xsd1:Login" />
  </wsdl:message>
  <wsdl:message name="LoginResponse">
    <wsdl:part name="parameters" element="xsd1:LoginResponse" />
  </wsdl:message>

在消息内放置哪些内容作为 <wsdl:part 标记的名称属性无关紧要,要注意的项目已用黑体表示。登录请求消息引用之前定义的 Login 元素,同样,LoginResponse 响应消息引用之前定义的 LoginResponse 元素。下面定义查找交易请求与响应消息,如 清单 13 所示。



清单 13. 查找交易请求与响应消息
  <wsdl:message name="LookupTransactions">
    <wsdl:part name="parameters" element="xsd1:LookupTransactions" />
  </wsdl:message>
  <wsdl:message name="LookupTransactionsResponse">
    <wsdl:part name="parameters" 
               element="xsd1:LookupTransactionsResponse" />
  </wsdl:message>

现在您应注意到了繁冗重复。就像登录请求与响应那样,您要命名查找交易请求和响应,引用之前定义的相关查找交易请求和响应元素。其他请求与响应也遵循同一模板。下面为您的在线银行 Web 服务定义端口类型。





回页首


端口类型

端口类型指定特定 Web 服务的操作。我们将定义端口类型和两个登录与查找交易操作。按 清单 14 定义端口类型和登录操作。



清单 14. 端口类型和登录操作
  <!-- Port type -->
  <wsdl:portType name="OnlineBankingPortType">

    <wsdl:operation name="Login">
      <wsdl: input message="tns:Login" />
      <wsdl: output message="tns:LoginResponse" />
    </wsdl:operation>

首先命名端口类型,在指定 WSDL 绑定时需要用到它。LoginLoginResponsetns: 前缀指定应在 tns 名称空间中查找消息,参见 清单 15 中的定义。现在定义查找交易操作。



清单 15. 查找交易操作
    <wsdl:operation name="LookupTransactions">
      <wsdl: input message="tns:LookupTransactions" />
      <wsdl: output message="tns:LookupTransactionsResponse" />
    </wsdl:operation>

再一次地,就像 Login 操作那样,定义 LookupTransactions 操作与之非常类似。接下来介绍 WSDL 绑定。





回页首


WSDL 绑定

WSDL 绑定指定消息格式、Web 服务的协议类型、在该端口上公开的操作。定义 WSDL 绑定和登录操作特有的绑定,如 清单 16 所示。



清单 16. WSDL 登录操作绑定
  <!-- Binding -->
  <wsdl:binding name="OnlineBankingPortBinding"
                type="tns:OnlineBankingPortType">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
                  style="document" />

    <wsdl:operation name="Login">
      <soap:operation
            soapAction="http://www.example.com/OnlineBanking/Login"
            style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

首先,命名绑定。现在注意类型。它引用了您在 清单 14 中定义的端口类型。<soap:binding 标记指定 Web 服务的传输方法和方式,分别为 http 和文档。<soap:body 指定输入和输出消息的编码方式。这里采用文字编码。接着定义查找交易操作的 WSDL 绑定,如 清单 17 所示。



清单 17. 查找交易操作的 WSDL 绑定
    <wsdl:operation name="LookupTransactions">
      <soap:operation
   soapAction="http://www.example.com/OnlineBanking/LookupTransactions"
   style="document" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>

这又一次与登录操作具有相似之处。其他操作也遵循这一模板。接下来继续介绍 WSDL 的最后一部分内容:服务标记。





回页首


服务标记

服务标记定义此 Web 服务公开了哪些端口。按 清单 18 进行服务定义。



清单 18. 服务定义
  <!-- Service -->
  <wsdl:service name="OnlineBankingService">

    <wsdl:port name="OnlineBankingPort"
               binding="tns:OnlineBankingPortBinding">
      <soap:address
location="http://localhost:8080/axis2/services/OnlineBankingService" />
    </wsdl:port>

  </wsdl:service>

首先命名服务,随后定义一个公开的端口 OnlineBankingPort,该端口引用您在 清单 17 中所定义的 WSDL 绑定。地址用于指定 Geronimo 上查找 Web 服务的 URL,也是收发 SOAP 请求的 URL。

下一节将 WSDL 编译为 Java 代码并在 Geronimo 上进行部署。





回页首

编译与部署 Web 服务

现在开始创建 Java 代码,它将实现在 WSDL 中定义的 Web 服务并使用 Axis2 在 Geronimo 上进行部署。

WSDL2Java

为创建 Web 服务的 Java 实现,请在您的 WSDL 文件上运行 WSDL2Java 工具。为此,键入以下代码(在 Microsoft® Windows® 中):

<axis2-binary-install-dir>/bin/WSDL2Java -d xmlbeans -uri ask.wsdl
-p com.ibm.axis2.onlinebanking -ss -sd


或(在 Linux® 中):

sh <axis2-binary-install-dir>/bin/WSDL2Java.sh -d xmlbeans
-uri ask.wsdl -p com.ibm.axis2.onlinebanking -sd


现在键入以下代码以创建用于测试的客户机存根(在 Windows 中):

<axis2-binary-install-dir>/bin/WSDL2Java -d xmlbeans -uri ask.wsdl
-p com.ibm.axis2.onlinebanking -ss -sd


或(在 Linux 中):

sh <axis2-binary-install-dir>/bin/WSDL2Java.sh -d xmlbeans
-uri ask.wsdl -p com.ibm.axis2.onlinebanking -sd


就是这样!现在 ./src 目录下应已创建好了 Java 源文件。方便的 Apache Ant build.xml 文件也会创建在此目录中。现在填充基本 Web 服务框架。





回页首


填充框架

为避免在测试 Web 服务时出现严重错误,需要在填充 Web 服务框架时使其永远不会返回 null。查看 ./src/com/ibm/axis2/onlinebanking/OnlineBankingPortTypeSkeleton.java 这一 Web 服务框架。打开并仔细观察该框架。您应注意到其中某处的 Login 方法,如 清单 19 所示。



清单 19. 原始 Web 服务
        public  com.example.www.onlinebanking.xsd.LoginResponseDocument Login
                  (com.example.www.onlinebanking.xsd.
                   LoginDocument param8 ){
                //Todo fill this with the necessary business logic
                return null;
        }

注意返回类型为 LoginResponseDocument,方法的参数为 LoginDocument(请求)。通过返回一个空的 LoginResponseDocument 填充示例定义,如 清单 20 所示。



清单 20. 示例定义
    public com.example.www.onlinebanking.xsd.
           LoginResponseDocument Login
        (com.example.www.onlinebanking.xsd.LoginDocument param8 ){
        LoginDocument.
            Login req =
            param8.getLogin();

        LoginResponseDocument res =
            LoginResponseDocument.Factory.newInstance();
        LoginResponseDocument.
            LoginResponse res2 =
            res.addNewLoginResponse();

        return res;
    }

在第一行中,从 param8 中获得实际 Login 请求对象(Axis2 在您的系统中生成的名称可能与此不同)。接下来在第三行中创建一个新的 LoginResponseDocument,添加新的 LoginResponse,返回空 res 对象 —— LoginResponseDocument

另外,不要忘记在顶端的包声明之下输入以下 import 语句:

package com.ibm.axis2.onlinebanking;
import com.example.www.onlinebanking.xsd.*;
...


这样在构建和部署 Web 服务时就不会遇到 class not found 错误了。





回页首


在 Geronimo 上部署 Axis2 和 Web 服务

首先,您需要构建 Web 服务。进入运行 WSDL2Java 工具的目录下,键入:

ant jar.server

这将创建一个 OnlineBankingService.aar 文件,路径为 ./build/lib/OnlineBankingService.aar。启动 Geronimo,部署此 Web 服务 Axis2 归档文件。键入以下命令引导 Apache Geronimo:

java -jar <geronimo-install-dir>/bin/server.jar

您已通过将 axis2.war 文件复制到 <geronimo-install-dir>/deploy 中而从 Apache 处下载了此文件,下面来部署此文件。打开浏览器,转到 http://localhost:8080/axis2/Login.jsp。

以用户名 admin、密码 axis2 登录。将您的浏览器转到 http://localhost:8080/axis2/upload.jsp。

单击 Browse,找到 OnlineBankingService.aar 文件,然后单击 Upload。在 20 到 30 秒内即可准备好 Web 服务。同时,下一节将为您介绍如何创建一个简单的客户机,以测试 Web 服务的初始功能。





回页首


创建和测试简单的客户机

为测试您的 Web 服务,应定义一个简单的客户机对其进行彻底的测试,确保正确传输 SOAP 消息。

导入类依赖性

创建客户机的第一步是导入类依赖性。创建 Client.java 文件,路径为 ./src/Client.java。按 清单 21 定义此文件。



















清单 21. 导入类依赖性
import com.example.www.onlinebanking.xsd.*;
import com.ibm.axis2.onlinebanking.*;

import java.util.*;

public class Client{

    public static void main(java.lang.String args[]){

您将使用的绝大多数对象都在前两个导入语句中,特别是客户机存根,还有请求与响应对象,以及 数据结构 一节中所定义的其他数据结构。下面开始定义主函数,首先声明客户机存根。

创建客户机存根

客户机存根使您可处理现运行于 Geronimo 之上的 Web 服务。按 清单 22 创建客户机存根。



清单 22. 客户机存根
    public static void main(java.lang.String args[]){
        OnlineBankingPortTypeStub stub = null;
        try{
            stub = new OnlineBankingPortTypeStub(null,
      "http://localhost:8080/axis2/services/OnlineBankingService");
...
        } catch(Exception e){
            e.printStackTrace();
        }
    }

将 Web 服务的 URL 传递给 OnlineBankingPortTypeStub 对象即可轻松完成对象的初始化。下面创建一些在调用和测试 Web 服务时使用的初始函数。





回页首


调用 Web 服务

本节内容也存在着重复的现象,因此这里只为您介绍在 Web 服务中调用 LoginLookupTransactions 操作的 API。掌握这种模板和 清单 25 中定义的函数调用后,即可轻松处理其余部分。首先定义调用 Login 操作的方法,如 清单 23 所示。



清单 23. 调用 Login 操作
    /* LOGIN */
    public static byte[] login(OnlineBankingPortTypeStub stub,
                               String username, String password){
        try{
            LoginDocument reqDoc00 = LoginDocument.
                Factory.newInstance();
            LoginDocument.Login reqDoc01 = reqDoc00.addNewLogin();

            LoginResponseDocument resDoc00 = stub.Login(reqDoc00);
            LoginResponseDocument.LoginResponse resDoc01 =
                resDoc00.getLoginResponse();

            return null;
        } catch(Exception e){
            e.printStackTrace();
        }
        System.out.println("Authorization failed");
        return null;
    }

在这里,我们轻松地创建了一个空的 LoginDocument 请求、将其发送给 Web 服务,然后接收一个空对象。如果一切顺利,则不会出现任何错误。清单 24 显示了定义 LookupTransactions 操作的原理示例。



清单 24. 调用 LookupTransactions 操作
                    
    /* LOOKUPTRANSACTIONS */
    public static boolean lookupTransactions(OnlineBankingPortTypeStub
                                             stub){
        try{
            LookupTransactionsDocument reqDoc00 =
                LookupTransactionsDocument.Factory.newInstance();
            LookupTransactionsDocument.
                LookupTransactions reqDoc01 =
                reqDoc00.addNewLookupTransactions();

            LookupTransactionsResponseDocument resDoc00 =
                stub.LookupTransactions(reqDoc00);
            LookupTransactionsResponseDocument.
                LookupTransactionsResponse resDoc01 =
                resDoc00.getLookupTransactionsResponse();

            return true;
        } catch(Exception e){
            e.printStackTrace();
        }
        return false;
    }

为其他所有操作创建类似的模板,这样您就可以对它们进行测试,为顺利学习本系列教程的第 2 部分作好准备。接下来一次性测试所有 Web 服务操作,调用方法(参见 清单 25)。



清单 25. 一次性测试所有 Web 服务操作
                    
...
            login(stub);
            lookupAccounts(stub);
            lookupTransactions(stub);
            searchTransactions(stub);
            viewPayee(stub);
            makeBillPayment(stub);
            changeBillPayment(stub);
            lookupPendingPayments(stub);
            addPayee(stub);
            lookupPayees(stub);
            editPayee(stub);
            transferFunds(stub);
            submitLoanApplication(stub);
            viewLoanApplicationStatus(stub);
            logout(stub);
        } catch(Exception e){
            e.printStackTrace();
        }
    }

调用各方法,传入存根,这样就作好了准备,可以构建并运行客户机了。





回页首


构建客户机,测试 Web 服务

您应该希望再次构建 Web 服务。像之前一样,键入以下命令来构建它:

ant jar.server

要运行客户机,向 build.xml 文件中添加一个新的 Ant 任务,如 清单 26 所示。



清单 26. 添加新 Ant 任务以运行客户机
                    
<!-- new target for running the client -->
    <target depends="jar.server" name="run.client">
        <java classname="Client" fork="true">
            <classpath>
                <path refid="axis2.class.path"/>
                <path location="${lib}/${name}.aar"/>
                <path location="${lib}/${xbeans.packaged.jar.name}"/>
            </classpath>
        </java>
    </target>

这样就创建好了一个运行客户机的新任务,键入以下命令即可运行客户机:

ant run.client

您应看到运行客户机的控制台输出,如 图 1 所示。



图 1. 运行客户机
运行客户机

服务器控制台输出(也就是运行 Geronimo 的控制台)应如 图 2 所示。



图 2. 服务器输出
服务器输出

此时,您或许会注意到,首次运行客户机要花费很长时间,这是因为 Web 服务需要在您的机器上加载并缓存自己。此后再运行客户机会快很多,您会注意到明显的速度提高。

至此,一切都很好!Web 服务正常运转了!





回页首


posted on 2006-12-29 19:40 SIMONE 阅读(1507) 评论(0)  编辑  收藏 所属分类: AXISJAVA

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


网站导航: