开发 web 服务,第 1 部分: 使用 Axis2 通过代码优先和契约优先方法开发 web 服务

本教程将演示如何通过使用 Axis2 运用代码优先(自下而上)方法开发 Credit Card Validation web 服务,然后运用契约优先(自上而下)方法开发 Product Catalog web 服务。代码优先方法是开发 web 服务最流行的方法,而契约优先方法是构建新 web 服务的正确方法。

Kuntal Ganguly, 初级开发人员, IBM China

Kuntal Ganguly目前在加尔各答 Protech Infosystems Pvt. Ltd 公司担任初级开发人员。Kuntal 曾经接触过广泛的开源和商业工具(WASCE、Eclipse、Mule ESB、EZlegacy、Active MQ、Birt 和 DB2 express C)以及各种技术(GWT 和 Android)



Partha Goswami, 初级开发人员, Protech Infosystems Pvt. Ltd

Partha Goswami目前在加尔各答 Protech Infosystems Pvt. Ltd 公司担任初级开发人员。他曾经接触过广泛的开源和商业工具(WAS CE、Eclipse、Mule ESB、EZlegacy、Active MQ、Birt 和 DB2 express C)和技术(GWT 和 RSS)。



2011 年 8 月 15 日

引言

本教程适用于通过不同方法使用 web 服务来构建应用程序的开发人员。通过使用 web 服务,您的应用程序可以向世界各地发布功能或消息。Web 服务使用 XML 对数据进行编码和解码,使用 SOAP 传输数据(使用开放协议)。

关于本系列

本系列教程讲述 web 服务的基本概念,以及使用不同的 SOAP 引擎(如 Apache AXIS2、 Apache CXF 和 JAX-WS)开发 web 服务的不同方法。本系列教程还提供了一个通过使用 MTOM (SOAP Message Transmission Optimization Mechanism) 发送带 SOAP 消息的大型附件的解决方案,MTOM 对 base64Binary 格式的二进制数据进行编码,并将数据作为二进制附件发送,而不是将它作为真正的 SOAP 消息。本系列还会演示如何通过使用 SAAJ API 进行简单的方法调用来读取和编写基于 SOAP 的 XML 消息,而且您可以选择通过 Internet 发送和接收此类消息。

第 1 部分 从简单的内容开始,先解释了 web 服务背后的基本概念,并展示了如何使用 Axis2 运用不同的方法(代码优先和契约优先)来开发 web 服务。

第 2 部分 首先使用 JAX-WS 简单地开发了一个 Hello User web 服务,然后进一步展示了一个使用 JAX-WS 和 MOTO 的 File Download web 服务(客户端可以通过 web 服务下载文件并存储在其所在的位置)示例。该部分还展示了如何从 SAAJ 客户端调用 web 服务。

第 3 部分 简单地展示了如何通过 XOP 实现、使用 Apache CXF 对 MTOM 的支持开发 File uploading web 服务(客户端可以上传文件/附件到 web 服务)。

关于本教程

本系列教程将会讲述使用不同的 Web 服务引擎(如 Axis2、JAX-WS 和 CXF)开发 web 服务的方法。Web 服务可用不同的应用程序协议实现,如 SOAP、XML、JSON、RESTful HTTP,且支持各种传输协议,如 HTTP 或 JMS (Java Message Service)。要创建 Web 服务,您需要一些工具。至少,你需要某种类型的 SOAP 处理引擎来解析接收到的消息,以及调用消息指向的函数或方法。市面上有很多产品提供这样的处理功能。所有 Web 服务开发工具的目标都是建立起 SOAP 处理器与在服务器上运行的业务逻辑之间的关系。通常,业务逻辑独立于 SOAP 处理逻辑。

在本系列教程的第 1 部分,您将了解如何通过使用 Axis2 运用代码优先(自下而上)方法开发 Credit Card Validation web 服务,然后运用契约优先(自上而下)方法开发 Product Catalog web 服务。

目标

在本教程中,您将学会如何:

  • 下载并安装 web 服务器(Tomcat)(如果还未安装),并对它做一些小配置以保证能成功实现样例。
  • 下载并安装 Axis2 引擎,生成存根和服务框架。
  • 下载并安装 Axis2 运行时环境到 Tomcat 中,以开发和部署 web 服务(Credit Card Validation 和 Product Catalog)。
  • 使用 Eclipse IDE 开发 web 服务的 POJO 客户端。

先决条件

本教程假设您对 Eclipse IDE 的基本概念和 web 服务架构有一定了解。


简介

什么是 web 服务?

web 服务是对应用程序功能的网络访问接口,它是使用标准 Internet 技术构建的。

我们目前看到的部署在 Internet 上的 web 服务都是 HTML 网站。其中,应用程序服务,即发布、管理、查找、检索内容的机制,是通过使用标准协议和数据格式访问的:HTTP 和 HTML。接受此标准的客户端应用程序(web 浏览器)能与应用程序交互,执行如订购图书、发送贺卡及阅读新闻的任务。由于基于标准的接口提供抽象机制,因此应用程序服务是否用 Java 编写以及浏览器是否用 C++ 编写,或者应用程序部署在 Unix 系统而浏览器部署在 Windows 系统上,这些都没有关系。Web 服务具有与平台无关的跨平台互操作性。互操作性是实现 web 服务的主要获益。分别基于 Java 和 Microsoft Windows 的解决方案通常很难集成,但应用程序与客户端之间的 web 服务层可大大消除其隔阂。

web 服务的好处

作为大众熟知的开放技术标准,web 服务可提供以下众多好处:

  • 增加供应商之间的竞争,从而降低产品成本。
  • 简化产品之间的转换,从而降低培训成本。
  • 提升各阵营产品互操作的能力,从而降低维护成本。
  • 能够更广泛地采用标准,使得标准可以延用更久。供应商和用户的广泛使用实现更高的接受度。

组织如何转向 web 服务

组织转向 Web 服务有三种主要方式。如下所述:

  1. 从头开始创建一个新的 web 服务(契约优先):开发人员创建服务的功能,并准备好描述服务的文档。
  2. 通过一个 web 服务来公开现有的功能(代码优先):此时,服务的功能已经有了。只需要实现服务描述。
  3. 对来自其他供应商或业务合作伙伴的 web 服务进行集成(中间相遇):有些情况下,在一个服务的基础上实现新服务比从头构建服务更加可行。在这些情况下,这些组织需要集成其他组织或业务合作伙伴的 Web 服务。

Web 服务概念的真正运用表现在第二个和第三个方法中,将我们引向可用于现有应用程序的其他 Web 服务和应用程序。

代码优先方法与契约优先方法

代码优先(自下而上)方法能让您通过公开现有应用程序来重用已有的投资。Credit Card System 是一个具有久经考验的商业价值的应用程序。竞争压力是转向 Credit Card System,以将其中的业务功能(如信用卡号验证)公开为 web 服务。实现类已经存在,需要做的就是创建 WSDL 并将类公开为 web 服务。

契约优先(自上而下)方法通常也称为 “纯方法”,这是从头构建新的 web 服务的正确方法。此方法首先是通过定义操作消息及类似信息构建 WSDL(契约)。然后构建端点接口,最后是实现类。

Axis2 架构

Axis2 构建在模块化架构之上,包含核心模块和非核心模块。核心引擎是一个纯 SOAP 处理引擎(此核心中没有任何 JAX-PRC 内容)。进入系统的每条消息必须先转换成 SOAP 消息,然后转交给核心引擎处理。进入的消息可以是 SOAP 消息,也可以是非 SOAP 的消息(REST JSON 或 JMX)。但在转换层,它会被转换成 SOAP 消息。在设计 Axis2 时,其架构中纳入了以下核心规则,以实现高度灵活和可扩展的 SOAP 处理引擎:

  • 逻辑与状态分离,以提供与状态无关的处理机制。(这是因为 web 服务是与状态无关的。)
  • 一个信息模型,以让系统能挂起和恢复。
  • 扩展到更新的 web 服务规范时对核心架构的改变最小。

Apache Axis2 架构构建在 SOAP 引擎的基础上。该引擎接受 SOAP 消息,对其解析,并调用 web 服务中合适的方法和函数。在细节层,Axis 就和其他 web 服务引擎一样。此产品以及其他所有产品的独特之处在于,开发人员如何组织处理过程以便让消息得到正确响应。


配置和开发

示例 I – 使用 AXIS2 的信用卡验证 web 服务

这是一个简单的使用代码优先方法的信用卡验证 web 服务,用户输入 16 位信用卡号码,对它进行验证并找出信用卡供应商。要设置并运行此示例,需要知道以下内容:

Eclipse IDE:集成开发环境(IDE)是可以编写、编辑、编译并运行计算机程序的一体化工具。而且 Eclipse 提供出色的集成开发环境。您可以在 www.eclipse.org 中找到最新版本的 eclipse。

Tomcat web server 5.5 或更高版本:Tomcat servlet 引擎是一个开源包,它是作为 Apache Software Foundation 的 Jakarta 项目的一部分开发的。这是 servlet 和 JSP 规范的官方参考实现。Tomcat 可作为独立的 Web 服务器以及 servlet/JSP 引擎。您可以在 http://tomcat.apache.org/download-60.cgi 中下载到最新版本的 Tomcat。

Axis2:

(二进制发行版): Axis2 二进制发行版包含所有相关的第三方库、一组样例和 Axis2 运行时。安装二进制版本需要将 ZIP 压缩文件解压到目标位置。下载并解压二进制版本后,您会看到它包含一组子目录(bin、lib、samples、repository、webapp)。

(War 发行版):Axis2 WAR 发行版对于在 Tomcat、Jboss、Weblogic 等应用程序服务器中部署 Axis2 非常有用。我们可以将 Axis2 WAR 文件部署到应用程序服务器中,并通过在浏览器中输入服务器地址来检查是否运行正常。例如,如果您在 Apache Tomcat 中部署了 Axis2 WAR 文件,通过输入 http://localhost:8080/axis2 就可以检查 Axis2 是否已启动并正在运行。

我们可以在 http://ws.apache.org/axis2/download.cgi 中下载到最新版本的 Axis2。每个 Axis2 发行版都包含四个主要发行项目或发行包:

  • 二进制发行版
  • WAR 发行版
  • 源代码发行版
  • JAR 发行版

设置环境

  1. 在系统中安装 JDK 1.5 或以上版本
  2. 下载 Axis2 文件(war 版本)之后,将 zip 文件解压到任何一个本地目录中。解压之后,您会看到 axis2.war 文件。将文件复制并粘贴到 <TOMCAT_HOME>webapp| 目录,然后启动 Tomcat。参见图 1. Tomcat 启动控制台。然后到 <TOMCAT_HOME>webapps| 目录,其中您会看到一个名为 axis2 的新目录,这表示 axis2.war 文件已成功部署。
  3. 下载 Axis2 二进制发行版并解压到一个目录中,此目录被称为 <AXIS2_HOME>。

开发 CreditCard 服务并在 Tomcat 中部署

  1. 为 Credit Card Validation Web 服务创建一个 Axis2Example 目录结构,如图 1 所示。
图 1. Axis2Example 项目目录结构
Axis2Example 项目目录结构
  1. 在 com.ibm.axis2.ccheck 包中创建一个 CheckSEI.java 接口,如下所示。
清单 1. CheckSEI.java
package com.ibm.axis2.ccheck;

import javax.jws.WebService;

@WebService (name="CheckCard",
		targetNamespace="http://ccheck.axis2.ibm.com")
		
public interface CheckSEI {
	
	public String doCheck(String targetName);
	
}
  1. 在 com.ibm.axis2.ccheck 包中创建一个 CheckCard.java 类,如清单 2 所示。
清单 2. CheckCard.java
package com.ibm.axis2.ccheck;
import javax.jws.WebService;
@WebService(serviceName = "CheckCardService",
		portName = "cport",
		endpointInterface = "com.ibm.axis2.ccheck.CheckSEI",
		targetNamespace = "http://ccheck.axis2.ibm.com")

public class CheckCard implements CheckSEI{
	
     	  public static final int INVALID          = -1;  
	  public static final int VISA             = 0;
	  public static final int MASTERCARD       = 1;
	  public static final int AMERICAN_EXPRESS = 2;
	  public static final int EN_ROUTE         = 3;
	  public static final int DINERS_CLUB      = 4;
	
	private static final String [] cardNames = 
    {   "Visa" , 
        "Mastercard", 
        "American Express", 
        "En Route", 
        "Diner's CLub/Carte Blanche",
    };

	public static boolean validCC(String number)
    throws Exception {   
    int CardID;
    if ( (CardID = getCardID(number)) != -1)
        return validCCNumber(number);
    return false;
    }

	public static boolean validCCNumber(String n) {
	    try {
	      
	      int j = n.length();
	  
	      String [] s1 = new String[j];
	      for (int i=0; i < n.length(); i++) s1[i] = "" + n.charAt(i);
	  
	      int checksum = 0;         
	    
	      for (int i=s1.length-1; i >= 0; i-= 2) {
	        int k = 0;
	        
	        if (i > 0) {
	           k = Integer.valueOf(s1[i-1]).intValue() * 2;
	           if (k > 9) {
	              String s = "" + k;
	              k = Integer.valueOf(s.substring(0,1)).intValue() + 
	                  Integer.valueOf(s.substring(1)).intValue();
	              }
	              checksum += Integer.valueOf(s1[i]).intValue() + k;            
	           }
	           else
	              checksum += Integer.valueOf(s1[0]).intValue();            
	        }
	      return ((checksum % 10) == 0);
	      }
	    catch (Exception e) {
	      e.printStackTrace();
	      return false;
	      }
	    }

	public static int getCardID(String number) {
	    int valid = INVALID;
	        
	    String digit1 = number.substring(0,1);
	    String digit2 = number.substring(0,2);
	    String digit3 = number.substring(0,3);
	    String digit4 = number.substring(0,4);
	    
	    if (isNumber(number)) {
	      
	      if (digit1.equals("4"))  {  
	        if (number.length() == 13 || number.length() == 16) 
	           valid = VISA;
	        }
	     
	      else if (digit2.compareTo("51")>=0 && digit2.compareTo("55")<=0) {
	        if (number.length() == 16) 
	           valid = MASTERCARD;
	        }
	      
	      else if (digit2.equals("34") || digit2.equals("37")) {
	        if (number.length() == 15) 
	           valid = AMERICAN_EXPRESS;
	        }
	    
	      else if (digit4.equals("2014") || digit4.equals("2149")) {
	         if (number.length() == 15) 
	            valid = EN_ROUTE;
	         }
	      
	      else if (digit2.equals("36") || digit2.equals("38") || 
	        (digit3.compareTo("300")>=0 && digit3.compareTo("305")<=0)) {
	        if (number.length() == 14) 
	           valid = DINERS_CLUB;
	           }
	      
	     	      
	      }           
	      return valid;
	      
	      
	      
	    }
	
	
	 public static boolean isNumber(String n) {
		    try  {
		      double d = Double.valueOf(n).doubleValue();
		      return true;
		      }
		    catch (NumberFormatException e) {
		      e.printStackTrace();
		      return false;
		      }
		    }

	 public static String getCardName(int id) {
		    return (id < -1 && id < cardNames.length ? cardNames[id] :"");
		    }

	
	 public String doCheck(String aCard){
		 
		 String s="";
		 boolean b;
		try{ 
		 if (getCardID(aCard) > -1) 
		 {
			  s="This is a  " + getCardName(getCardID(aCard)) + " Card .";
			if( b=validCC(aCard))
			{
				s=s+"The card number " + aCard + " is VALID " ;
			}
			else{s= s+"The card number " + aCard + " is IN-VALID " ;}
		 }
		
		 else{return("INVALID INPUT");}
		}		
		catch(Exception e){}
		 return(s);
	 }
	
	
	
}
  1. 在 META-INF 目录内创建一个 services.xml 文件,如清单 3 所示。
清单 3. Services.xml
<service>
   <description>
      This Web Service Validates CreditCard Number.
   </description>
   <parameter name="ServiceClass">com.ibm.axis2.ccheck.CheckCard</parameter>
   <operation name="doCheck">
      <messageReceiver
      class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
   </operation>   
</service>
  1. 现在通过在 START > Run 中输入 cmd 来打开命令提示符。见图 2。
图 2. 打开命令提示符
打开命令提示符
  1. 转向 ccheck 目录并输入 javac *.java,如下所示(要想从 Axis2Example 项目目录运行 javac 命令,需要将 <JAVA_HOME>bin| 设置为用户变量的路径)。
图 3. 编译 CreditCard 接口和类
编译 CreditCard 接口和类
  1. 现在转向 Code First Service 目录,如下所示输入 jar cvf CreditCardService.aar * 以生成 aar 文件。(见图 4)
图 4. 生成 CreditCardService.aar 文件
生成 CreditCardService.aar 文件
  1. 启动 tomcat 并通过输入 /localhost:8080/axis2 来打开浏览器,然后单击 Administration。
图 5. 在 Tomcat 上运行 Axis2
在 Tomcat 上运行 Axis2

登录时您需要提供默认用户名 admin 和密码 axis2,如图 6 所示。

图 6. 以 Axis2 管理员身份登录
以 Axis2 管理员身份登录
  1. 成功登录后,单击 Upload web service,然后会在 Axis2Example|Code First Service 目录中看到 CreditCardService.aar 文件,最后单击 Upload(以成功部署 web 服务),如图 7 所示。
图 7. CreditCardService 上传
CreditCardService 上传
  1. 现在,单击 Available Service 或者在浏览器中粘贴 http://localhost:8080/axis2/axis2-admin/listService,找到已部署的 CreditCard web 服务,如图 8 所示。
图 8. CreditCard 服务部署
CreditCard 服务部署
  1. 单击服务,在 http://localhost:8080/axis2/services/CheckCardService?wsdl 上检查 CreditCardService 的 WSDL。

生成存根

  1. 打开命令提示符,转到 <AXIS2_HOME>bin| 目录,并输入如下命令,如图 9 所示。

wsdl2java.bat -uri http://localhost:8080/axis2/services/CheckCardService?wsdl -o client

图 9. 生成 Credit Card 服务的存根
生成 Credit Card 服务的存根

(您会看到存根名称:CheckCardServiceCallbackHandler.java、CheckCardServiceStub.java 和 ExceptionException.java 在 <AXIS2_HOME>|bin|src|com|ibm|axis2|ccheck| 目录中生成)。

为 CreditCardService 开发 POJO 客户端

  1. 在 Eclipse 中,选择 Create File > New > Java Project,该项目名为 Axis2Client,如图 10 所示。
图 10. Eclipse 中的 Axis2Client Java 项目
Eclipse 中的 Axis2Client Java 项目
  1. 在 Axis2Client|src 文件夹下创建一个 com.ibm.axis2.ccheck 包,如图 11 所示。
图 11. 为 Axis2Client 创建一个程序包
为 Axis2Client 创建一个程序包
  1. 现在选择 Axis2Client 项目,并配置构建路径,如图 12 所示。
图 12. 配置 Axis2Client 的构建路径
配置 Axis2Client 的构建路径

单击 Add External JARs 并选择 <AXIS2_HOME>lib| 中所有的 jar 文件,然后单击 OK。

  1. 现在,复制生成的存根并将其粘贴到 Axis2Client 项目的 com.ibm.axis2.ccheck 包中,如图 13 所示。
图 13. 复制并粘贴生成的存根
复制并粘贴生成的存根
  1. 现在,在 com.ibm.axis2.ccheck 包中创建一个 TestClient.java 类,如下所示。
清单 4. Services.xml
package com.ibm.axis2.ccheck;
import java.io.*;
import com.ibm.axis2.ccheck.*;

public class TestClient {
     public static void main(String[] args) throws Exception {
         CheckCardServiceStub stub = new CheckCardServiceStub();
         //Create the request

    com.ibm.axis2.ccheck.CheckCardServiceStub.DoCheck  request = new 
   com.ibm.axis2.ccheck.CheckCardServiceStub.DoCheck();
    System.out.println("Enter your Credit Card Number:");
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(isr);
    String s = br.readLine();
    
        request.setArgs0(s);
         //Invoke the service
        com.ibm.axis2.ccheck.CheckCardServiceStub.DoCheckResponse response 
            = stub.doCheck(request);
        System.out.println(response.get_return());
    }
}
  1. 选择 TestClient.java,然后是 Run As > Java Application(确保 Tomcat 正在运行)。
  2. 运行 TestClient 之后,控制台会提示您输入信用卡号,如下所示:

    (例如,输入以下号码 4111111111111111 然后按 ENTER 键获取有效信息和有效供应商)
图 14. 在控制台输入有效的信息和供应商
在控制台输入有效的信息和供应商

(例如,输入以下号码 5111111111111111 然后按 ENTER 键获取有效信息和有效供应商)。

图 15. 输入无效的信息和有效的供应商
输入无效的信息和有效的供应商

(输入一个无效的信用卡号,例如 51470965,然后按 ENTER 键以获取无效信息)。

图 16. 输入无效信息
输入无效信息

示例 II - 使用 Axis2 通过契约优先方法开发 Product Catalog 服务

这是通过契约优先方法开发的一个很简单的 Product Catalog web 服务,用户将输入 ProductId 号以在目录中找到想要的产品名称。要安装并运行此样例,需要知道以下内容:

Ant:Apache Ant 是 Java 库和命令行工具,它的任务是推动构建文件中描述的过程作为目标和互相依赖的扩展点。Ant 的主要用途是构建 Java 应用程序。Ant 提供了大量内置任务,可用来编译、汇编、测试和运行 Java 应用程序。Ant 还可以有效地构建非 Java 应用程序,例如 C 或 C++ 应用程序。更常见的是,Ant 可用来试验任何类型的过程,这些过程可从目标和任务方面加以描述。可以在 http://ant.apache.org/bindownload.cgi 中下载到最新版本的 ANT。

设置环境

  1. 将 <ANT_HOME>bin| 设置为用户变量路径。(其他的环境设置和示例-I 类似)。

开发 WSDL

  1. 在 <AXIS_HOME>bin|wsdl| 目录下创建一个名为 product.wsdl 的文件,如下所示
清单 5. product.wsdl
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" 
xmlns:ns1="http://org.apache.axis2/xsd"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" 
xmlns:ns="http://contract.axis2.ibm.com" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    targetNamespace="http://contract.axis2.ibm.com">
    
        <wsdl:types>
        <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://contract.axis2.ibm.com">
            <xs:element name="getProductName">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="productNumber" type="xs:int"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
                        
            <xs:element name="getProductNameResponse">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="return" nillable="true" 
                                        type="xs:string"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:schema>
    </wsdl:types>
        
    <wsdl:message name="getProductNameRequest">
        <wsdl:part name="parameters" element="ns:getProductName"/>
    </wsdl:message>
        
    <wsdl:message name="getProductNameResponse">
        <wsdl:part name="parameters" element="ns:getProductNameResponse"/>
    </wsdl:message>
        
    <wsdl:portType name="ProductPortType">
        <wsdl:operation name="getProductName">
            <wsdl:input message="ns:getProductNameRequest" 
                        wsaw:Action="urn:getProductName"/>
            <wsdl:output message="ns:getProductNameResponse" 
                        wsaw:Action="urn:getProductNameResponse"/>
        </wsdl:operation>
    </wsdl:portType>
        
    <wsdl:binding name="ProductSoap11Binding" type="ns:ProductPortType">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
                          style="document"/>
        <wsdl:operation name="getProductName">
            <soap:operation soapAction="urn:getProductName" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
        
    <wsdl:binding name="ProductSoap12Binding" type="ns:ProductPortType">
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" 
                          style="document"/>
        <wsdl:operation name="getProductName">
            <soap12:operation soapAction="urn:getProductName" style="document"/>
            <wsdl:input>
                <soap12:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
        
    <wsdl:binding name="ProductHttpBinding" type="ns:ProductPortType">
        <http:binding verb="POST"/>
        <wsdl:operation name="getProductName">
            <http:operation location="Product/getProductName"/>
            <wsdl:input>
                <mime:content type="text/xml" part="getProductName"/>
            </wsdl:input>
            <wsdl:output>
                <mime:content type="text/xml" part="getProductName"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
        
    <wsdl:service name="Product">
        <wsdl:port name="ProductHttpSoap11Endpoint" binding="ns:ProductSoap11Binding">
            <soap:address location="http://localhost:8080/axis2/services/Product"/>
        </wsdl:port>
        <wsdl:port name="ProductHttpSoap12Endpoint" binding="ns:ProductSoap12Binding">
            <soap12:address location="http://localhost:8080/axis2/services/Product"/>
        </wsdl:port>
        <wsdl:port name="ProductHttpEndpoint" binding="ns:ProductHttpBinding">
            <http:address location="http://localhost:8080/axis2/services/Product"/>
        </wsdl:port>
    </wsdl:service>
        
</wsdl:definitions>
  1. 使用 <AXIS2_HOME>|bin|wsdl2java.bat 工具,我们就可以创建该服务的框架和其他受支持文件。
  2. 打开命令提示符,转到 <AXIS2_HOME>|bin| 并执行以下命令
    wsdl2java.bat –uri <AXIS2_HOME>\bin\wsdl\product.wsdl -d adb -s -ss -sd -ssi -o build\service
  3. 这将会在 <AXIS2_HOME>|bin|build| 目录中生成名为 service 的输出,如图 17 所示。
图 17. 产品目录的服务框架目录结构
产品目录的服务框架目录结构

target_directory_name 的内容有:

build.xml
resources\services.xml
resources\product.wsdl
src|com|ibm|axis2|contract|ExtensionMapper.java
src|com|ibm|axis2|contract|GetProductName.java
src|com|ibm|axis2|contract|GetProductNameResponse.java
src|com|ibm|axis2|contract|ProductMessageReceiverInOut.java
src|com|ibm|axis2|contract|ProductSkeleton.java
src|com|ibm|axis2|contract|ProductSkeletonInterface.java

在以上列表中,名为 src|com|ibm|axis2|contract|ProductSkeleton.java 的 Java 文件是我们用来放置自定义业务逻辑代码的地方。

自动生成的 ProductSkeleton java 代码

清单 6. 自动生成的 ProductSkeleton.java
/**
 * ProductSkeleton.java
 * This file was auto-generated from WSDL
 * by the Apache Axis2 version:1.5.2  Built on :Sep 06, 2010 (09:42:01 CEST)
 */
    package com.ibm.axis2.contract;
    /**
     *  ProductSkeleton java skeleton for the axisService
     */
    public class ProductSkeleton implements ProductSkeletonInterface{
     /**
         * Auto generated method signature
          * @param getProductName0
         */
        public com.ibm.axis2.contract.GetProductNameResponse getProductName
                  (
                  com.ibm.axis2.contract.GetProductName getProductName)
                 {
                
                throw new java.lang.UnsupportedOperationException("Please implement " 
                                + this.getClass().getName()
                                + "#getProductName");
        }
}

我们在以上类中添加业务逻辑以实现其功能。

清单 7. 添加到 ProductSkeleton.java 中的业务逻辑
/**
 * ProductSkeleton.java
 * This file was auto-generated from WSDL
 * by the Apache Axis2 version:1.5.2  Built on :Sep 06, 2010 (09:42:01 CEST)
 */
 package com.ibm.axis2.contract;
import com.ibm.axis2.contract.*;
import java.util.*;
import org.apache.axis2.engine.AxisError;
    /**
     *  ProductSkeleton java skeleton for the axisService
     */
    public class ProductSkeleton implements ProductSkeletonInterface{
        private static HashMap<Integer, String> productMap   = new
HashMap<Integer, String>();
        static
        {   productMap.put(1, "Colgate");
                productMap.put(2, "Pepsodent");
                productMap.put(3, "Neem");    }
      /**
         * Auto generated method signature
          * @param getProductName0
         */      
public com.ibm.axis2.contract.GetProductNameResponse 
        getProductName ( com.ibm.axis2.contract.GetProductName getProductName)
                   {
                 /* Custom Logic - Starts here */
                int inputProductNumber = getProductName.getProductNumber();
                String productName = productMap.get(inputProductNumber);
                GetProductNameResponse response = new GetProductNameResponse();
                if (productName != null)
                {   response.set_return(productName);
                }
                else
                { throw new AxisError("Product Record Not Found");  }
               return response;
                /* Custom Logic - Ends here */
 } 
 }
  1. 现在可以构建并测试 web 服务实现了。
  2. 打开命令提示符,转到 <AXIS2_HOME>bin|build|service| 并输入以下命令,如下所示。

    Ant jar.server
图 18. 使用 ANT 进行构建和测试
使用 ANT 进行构建和测试

以上的 ANT 构建将会在 <AXIS2_HOME>bin|build|service|build|lib| 中创建一个 Product.aar 文件,如下所示

图 19. ANT 构建目录结构和 Product.aar 文件
ANT 构建目录结构和 Product.aar 文件

将 web 服务部署到 Tomcat

部署 Product.aar 文件的步骤与在 tomcat 上部署 CreditCardService 类似。

  1. 启动 tomcat 并通过输入 /localhost:8080/axis2 来打开浏览器,然后单击 Administration。(您需要提供默认用户名 admin 和密码 axis2 进行登录)。
  2. 成功登录后,单击 Upload web service,然后会在 <AXIS2_HOME>bin|build|service|build|lib| 目录中看到 CreditCardService.aar 文件,最后单击 Upload(以成功部署 web 服务)。
  3. 现在,单击 Available Service 或者在浏览器中粘贴 http://localhost:8080/axis2/axis2-admin/listService,找到已部署的产品服务,如下所示。
图 20. 产品服务部署
产品服务部署

您可以在 http://localhost:8080/axis2/services/Product?wsdl 中查看 Product web 服务的 WSDL。


结束语和资源

通过本教程,您用了很短的时间学习了如何使用 Axis2 通过代码优先和契约优先方法开发 web 服务。在本系列教程的第 2 部分中,您将了解如何使用 JAX-WS 开发 File Download web 服务,并在 SAAJ 客户端使用它。


下载

描述名字大小
本文的 Perl 脚本样例code.zip10KB

参考资料

学习

讨论

条评论

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=SOA and web services
ArticleID=752366
ArticleTitle=开发 web 服务,第 1 部分: 使用 Axis2 通过代码优先和契约优先方法开发 web 服务
publish-date=08152011