Axis初见端倪

前言

什么是Axis项目

        在它的核心,Axis 项目是第三代简单对象访问协议(SOAP)的引擎。在最高级别上,它是一个用SOAP来创建和部署能共同操作的XML事务的完善的框架。Axis项目是一个开源的基于SOAP v1.1的Java执行规范。

什么是SOAP

         依照W3C,“SOAP是一个特意用于在一个分散的,分布式的环境下信息的交换组织”。换句话说,SOAP是和用XML作为通信层,在不同网络协议上通信的用起来简单的方法相关的。它是一个起到杠杆作用的电报协议,把HTTP作为它的传输层,并把XML作为它的数据层来执行远程方法,就是众所周知的SOAP/Web服务。
        在历史上,SOAP是被像Microsoft,IBM,还有其他几个公司提出引入的。当前规范是SOAP v1.1 。然而,W3C已经发布SOAP 1.2的一个工作草稿,它使1.1规范很让人迷惑的一些地方神秘化了。
        Axis实现了SOAP执行规范中提供的调用SOAP服务的四个方法:
          • Remote Procedure Call (RPC)
          • Document
          • Wrapped
          • Message
         远程过程调用(RPC)服务
        
RPC方法是一个用在C/S模式下执行远程SOAP服务的一种同步技术。这种模式通过下列定义:
        1.客户端应用建立一个XML文档,文档里面包括提供请求服务的服务器的 
            URI,在服务器端执行的方法名,和与该方法关联的参数。
        2.目标服务接受并展开XML文档,然后执行指定的方法。
        3.当指定的方法执行后返回它的结果时,Axis把它们映射到一个响应XML文
           档,然后送回给调用的客户端。
        4.客户端接收到这响应并展开包含被调用方法的响应结果。
        文档和包装服务
       文档和包装服务是非常相似的,因此放在一起讨论。在既不用SOAP-style绑定它们的数据表现层,而且它们关联数据的打包也不是作为一个简单的XML schema数据的RPC服务里面,这两者就不同了。
       文档和包装服务只有在它们被实际的实现服务所处理这种方式下它们才彼此不同,文档服务有一个类似于下面的schema:
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
              targetNamespace="http://www.sourcebeat.com/Person">
        <xs:element name="person">
        <xs:complexType>
        <xs:sequence>
        <xs:element name="first" type="xsd:string"/>
        <xs:element name="last" type="xsd:string"/>
        </xs:sequence>
        </xs:complexType>
       </xs:element>
       </xs:schema>
文档服务将会调用具有下面签名的一个服务方法:
      public void methodName(Person person);
包装服务将会调用具有下面解开的签名的一个服务方法:
      public void methodName(String first, String last);
      注意:上面两种方法的命名并不重要,仅仅重要的是它们的参数列表。
     消息服务
      最后,被Axis项目提供的SOAP服务方法是消息(Message)服务。当你想提供一个具有直接访问XML数据的服务的时候就用到消息服务,而作为反对的做法是让Axis把Message映射到Java对象中。假如有兴趣观察一个消息服务是如何被构建的,可以在Axis的压缩包里面找到一个例子:<AXIS_HOME>/samples/message/MessageService.java

 创建和部署Web Service
         创建一个基于SOAP的RPC服务是一件用两个步骤就可以搞定的简单的事情。下面分两部分描述这些步骤。
创建一个执行服务
         一个SOAP服务应当能被任何暴露公共方法的Java类所使用,这些类并不需要知道任何有关SOAP的情况,甚至它自己是作为一个SOAP服务执行着。唯一的限制是它的方法的参数必须被序列化。举个例子,创建一个将要扮演着比较乏味的存货管理人员角色的Web Service。这将包含着三个类:第一个是Web Service自己本身(清单1);第二,第三个是包含支持这服务的商业逻辑(清单2和清单3)。
import ch02.InventoryItem;
/**
 * @desc 存货服务的实现
 * @author chikai
 * @link <a href="mailto:wzj616@etang.com">chikai</a>
 * @version $ InventoryService.java  2004-12-7 11:49:30 $
 * @version $ Project webservice
 */
public class InventoryService {
    public int addInventory(String sku, int quantity) {
        InventoryItem item = new InventoryItem(sku, quantity);
        System.out.println(item);
        return (ch02.Inventory.addInventory(item)).getQuantity();
    }
    public int reduceInventory(String sku, int quantity) {
        InventoryItem item = new InventoryItem(sku, quantity);
        System.out.println(item);
        return (ch02.Inventory.reduceInventory(item)).getQuantity();
    }
    public int getInventoryQuantity(String sku) {
        InventoryItem item = ch02.Inventory.getInventoryItem(sku);
        return item.getQuantity();
    }
}
清单1  : InventoryService.java - 存货服务的实现
         这存货服务是一个包含三个公共方法的简单的Java类:addInventory(),
reduceInventory(), 和getInventoryQuantity()。每个方法将接受它们关联的签名方法的简单Java类型。下面清单2显示的是在这服务里面用到的InventoryItem:
package ch02;

import java.io.Serializable;

/**
 * @desc InventoryItem Bean
 * @author chikai
 * @link <a href="mailto:wzj616@etang.com">chikai</a>
 * @version $ InventoryItem.java  2004-12-7 11:50:24 $
 * @version $ Project webservice
 */
public class InventoryItem implements Serializable{
    public String sku = null;
    public int quantity = 0;
    public InventoryItem() {
    }
    public InventoryItem(String sku, int quantity) {
        this.sku = sku;
        this.quantity = quantity;
    }
    public String getSku() {
        return sku;
    }
    public void setSku(String sku) {
        this.sku = sku;
    }
    public int getQuantity() {
        return quantity;
    }
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }
    public String toString() {
        return ("SKU = " + sku + " QUANTITY = " + quantity);
    }
}
清单2 :InventoryItem.java-InventoryItem Bean
这是描述一个存货单的简单Bean。
注意:为什么InventoryItem不直接传递Integers和String 呢?答案是Axis需要额外的配置来传递非原生的对象。
       第三个类大和复杂一点,但并不令人讨厌的。它实际上为我们的Web Service封装了商业逻辑。
        package ch02;

import java.util.Hashtable;

/**
 * @desc 存货商业逻辑实现
 * @author chikai
 * @link <a href="mailto:wzj616@etang.com">chikai</a>
 * @version $ Inventory.java  2004-12-7 11:51:23 $
 * @version $ Project webservice
 */
public class Inventory {
    private static Hashtable inventory = new Hashtable();
    public static InventoryItem addInventory(InventoryItem item) {
        System.out.println("ADDING : " + item);
        if ( inventory.containsKey(item.getSku()) ) {
            InventoryItem currentItem =(InventoryItem)inventory.get(item.getSku());
            currentItem.setQuantity(currentItem.getQuantity() +
                    item.getQuantity());
        }
        else {
            inventory.put(item.getSku(), item);
        }
        return (InventoryItem)inventory.get(item.getSku());
    }
    public static InventoryItem reduceInventory(InventoryItem item) {
        InventoryItem currentItem = null;
        if ( inventory.containsKey(item.getSku()) ) {
            currentItem =(InventoryItem)inventory.get(item.getSku());
            currentItem.setQuantity(currentItem.getQuantity()-item.getQuantity());
        }
        else {
            //      this is an error and will be handled in Chapter 5
        }
        return currentItem;
    }
    public static InventoryItem getInventoryItem(String sku) {
        InventoryItem item = null;
        if ( inventory.containsKey(sku) ) {
            item = (InventoryItem)inventory.get(sku);
        }
        else {
            //     this is an error and will be discussed in Chapter 5
        }
        return item;
    }
}
清单3  : Inventory.java -存货商业逻辑实现
部署Web Service
       这一部分描述Web Service的部署过程-一个警告,你事实上将会看到一个Axis部署描述符,但没用到它。
       Axis标准的部署方法是用一些众所周知的东西,像Web Service部署描述符,或者WSDD文件,虽然这听起来有点复杂,它事实上是一个非常简单的XML文件,用来描述我们的Web Service和一些关联属性,这有一个可以用来部署Web Service的简单例子:
    <deployment xmlns="http://xml.apache.org/axis/wsdd/"
                           xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
       <service name="InventoryService" provider="java:RPC">
           <parameter name="className" value="ch02.InventoryService"/>
            <parameter name="allowedMethods" value="*"/>
       </service>
    </deployment>
就像所看到的一样,这个文件并不非常复杂,它包含一对现在可以忽略的名称空间,然后是一个<service >元素和两个<parameter>子元素,这些被用来描述这Web Service和它如何被部署。不要过多聚焦在这个文件上面,我们并不打算现在就用它,这仅仅是为了我们了解一下正常它是怎么处理的。
         我们当前的目的就是打算用一个简单的Axis的部署形式-自动发布。它是一个可以分为三个步骤的简单过程:
          注意:这种方法是有局限性的,并不被推荐。自动发布(JWS类型)的web服务是针对提供简单功能的web服务而设计的,这种web服务只有经过发布之后才能知道是否存在错误,所以如果web服务需要实现比较复杂业务逻辑或者是某种商业产品的一部分,还是需要使用定制发布的web服务。
         1.修改服务执行源文件的扩展名;
             InventoryService.java -> InventoryService.jws
         2. 拷贝刚刚修改的文件到我们机器的WEB应用目录下;
             <TOMCAT_HOME>/webapps/axis/ch02
         3.编译并拷贝相关类文件到我们机器的WEB应用下面的classes目录下,我们的
             例子的类文件是ch02/InventoryItem.class 和ch02/Inventory.class,目录是
             <TOMCAT_HOME>/webapps/axis/WEB-INF/classes/ch02
         至此,我们完成了Web Service的隐含部署,并能被如何知道该服务的客户端执行了。

创建客户端
         现在写一个将要执行服务的方法的客户端,Axis项目提供一个使简单的创建SOAP客户端的client-side API。
package ch02;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import javax.xml.rpc.ParameterMode;
/**
 * @desc 存货客户端(测试)
 * @author chikai
 * @link <a href="mailto:wzj616@etang.com">chikai</a>
 * @version $ InventoryClient.java  2004-12-7 13:49:08 $
 * @version $ Project webservice
 */
public class InventoryClient {
    public Integer addInventory(String endpoint)
    throws Exception {
        String method = "addInventory";
        String sku = new String("SKU456");
        Integer quantity = new Integer(8);
        Service service = new Service();
        Call call = (Call) service.createCall();
        call.setTargetEndpointAddress(new java.net.URL(endpoint));
        call.setOperationName(method);
        call.addParameter("sku", XMLType.XSD_STRING,
                ParameterMode.IN);
        call.addParameter("quantity", XMLType.XSD_INT,
                ParameterMode.IN);
        call.setReturnType(XMLType.XSD_INT);
        Object parameters[] = new Object[] {sku, quantity};
        return (Integer)call.invoke(parameters);
    }
    public Integer reduceInventory(String endpoint)
    throws Exception {
        String method = "reduceInventory";
        String sku = new String("SKU456");
        Integer quantity = new Integer(2);
        Service service = new Service();
        Call call = (Call) service.createCall();
        call.setTargetEndpointAddress(new java.net.URL(endpoint));
        call.setOperationName(method);
        call.addParameter("sku", XMLType.XSD_STRING,
                ParameterMode.IN);
        call.addParameter("quantity", XMLType.XSD_INT,
                ParameterMode.IN);
        call.setReturnType(XMLType.XSD_INT);
        Object parameters[] = new Object[] {sku, quantity};
        return (Integer)call.invoke(parameters);
    }
    public Integer getInventoryQuantity(String endpoint)
    throws Exception {
        String method = "getInventoryQuantity";
        String sku = new String("SKU456");
        Service service = new Service();
        Call call = (Call) service.createCall();
        call.setTargetEndpointAddress(new java.net.URL(endpoint));
        call.setOperationName(method);
        call.addParameter("sku", XMLType.XSD_STRING,
                ParameterMode.IN);
        call.setReturnType(XMLType.XSD_INT);
        Object parameters[] = new Object[] {sku};
        return (Integer)call.invoke(parameters);
    }
    public static void main(String[] args) throws Exception {
        String endpoint =
            "http://localhost:8080/axis/ch02/InventoryService.jws";
        InventoryClient client = new InventoryClient();
        Integer ret = client.addInventory(endpoint);
        System.out.println("Adding Got result : " + ret);
        ret = client.reduceInventory(endpoint);
        System.out.println("Removing Got result : " + ret);
        ret = client.getInventoryQuantity(endpoint);
        System.out.println("Getting Got result : " + ret);
    }
}
清单4  :InventoryClient.java-存货客户端
       当Axis Web应用接收到一个扩展名是.jws的文件的请求时,它将会认可这是一个特别的的扩展名,这是因为我们在web.xml文件里面已经映射相应的请求到AxisServlet,由它处理。看下面的web.xml文件:
<?xml version="1.0" ?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<!-- Copyright (c) 2002 by ObjectLearn. All Rights Reserved. -->
<web-app>
<!-- configure the Axis servlet. Axis provides eXist's
web-services via SOAP -->
  <servlet>
    <servlet-name>AxisServlet</servlet-name>
    <display-name>Apache-Axis Servlet</display-name>
    <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>AdminServlet</servlet-name>
    <display-name>Axis Admin Servlet</display-name>
    <servlet-class>org.apache.axis.transport.http.AdminServlet</servlet-class>
    <load-on-startup>100</load-on-startup>
  </servlet>
   
<!-- Axis servlets -->
  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>*.jws</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>AxisServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>
</web-app>
      下面我们来解释一下InventoryClient .java文件里面的一些用法。
       String method = "addInventory";
      这是我们在InventoryService里面指定的一个方法名。
      接下来,我们将要创建两个传递给Web Service的对象:sku和quantity,在InventoryItem对象里已经被全部映射为KEY/VALUE键值对。
      String sku = new String("SKU456");
      Integer quantity = new Integer(8);
      
        这是我们开始用一些Axis APIs的地方,首先,一个org.apache.axis.client.Service被创建,这个Service是创建org.apache.axis.client.Call对象的工厂类,Call是实际调用Web Service的对象。
        Service service = new Service();
        Call call = (Call) service.createCall();

        一旦拥有一个Call实例,开始设置Web Service需要调用的属性。第一个属性是设置目标Web Service的地址,这个实例中传递给这个方法的是一个String:http://
localhost:8080/axis/InventoryService.jws。
         call.setTargetEndpointAddress(new java.net.URL(endpoint));
         或者call.setTargetEndpointAddress(“http://localhost:9080/axis/HelloWorld.jws“);
        下个属性是设置将被调用的方法名:addInventory。
         call.setOperationName(method);
         下部分的代码有点能引起兴趣:
          call.addParameter("sku",XMLType.XSD_STRING, ParameterMode.IN);
          call.addParameter("quantity",XMLType.XSD_INT, ParameterMode.IN);
         匆匆一看,它好像是我们将要加被Web Service用到的参数名和值。事实上,我们是在告诉Axis所期望的两个参数,sku和quantity。它们各自的值的类型将是String和Integer。将绑定到这请求上的真正的参数值实际上还没被设置,要等到Call.invoke()方法被调用时。
         最后的一个属性是设置期望要返回的结果类型,在这个例子中是Integer。
         call.setReturnType(XMLType.XSD_INT);
         现在,所有的属性已经被设置了,是时间调用我们的Web Service了。就像先前讨论的,Axis已经被告诉所期望的了,但事实上,并没有参数值被传递给Call实例。为了做到这点,把所有的参数加到一个数组对象,然后传递这个数组对象给Call.invoke()方法,就像下面所做的:
         Object parameters[] = new Object[] {sku, quantity};
         return (Integer)call.invoke(parameters);
        当这方法被调用时,它将会调用Web Service Inventory的addInventory()方法并且传递sku and quantity这两个值。当调用完成后,它将会返回一个addInventory()运算结果为Integer类型的值。
         至此,该是我们享受成果的时候了。在客户端浏览器敲入下面连接地址:
http://localhost:8080/axis/ch02/InventoryService.jws?wsdl,我们将会看到像下面图片看到的一样:
http://blog.csdn.net/images/blog_csdn_net/chikai/76624/r_ws.gif


编译并执行InventoryClient,如果一切顺利的话,我们将会看到下面的打印信息:
Adding Got result : 8
Removing Got result : 6
Getting Got result : 6

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值