Apache axis用户指南_2

 
本部分是 apache axis 用户指南的第二部分。
5. 服务 Styles---RPC,Document,Wrapped 和消息
Axis 支持四种样式的服务。
RPC 服务使用 SOAP RPC 惯例和 SOAP section 5 的编码。 Document 服务部使用任何编码方式 ( 所以,不会看到多饮用的对象序列化或者 SOAP-style 数组 ) ,但是使用 XML<-->Java 数据绑定。 Wrapped 服务和 document 服务相似,但是 Wrapped 服务不是将整个 SOAPbody 绑定到一个大的结构,而是将它分成很多个体参数。 Message 服务接受和返回任意 SOAP Envelope 中的 XML ,并不进行类型映射和数据绑定。
如果只想使用原始的 XML 作为 SOAP Envelope 的输入和输出,那么就是用 message 服务。
RFC服务
RFC 服务是 Axis 的默认服务。它们在部署描述符中的定义为 <service....provider=”java:RPC”> 或者 <service....style=”RPC”> RPC 服务遵循 SOAP RPC 和编码规则,这意味着 RPC 服务的 XML 就像上面的 echoString 例子一样,每个 RPC 调用都作为操作名,包含的内部元素对应操作的参数。 Axis 会将 XML 反序列化成 Java 对象来适应服务,然后再将返回的 Java 对象进行序列化成 XML 返回。由于 RPC 服务默认使用 soap section 5 比阿玛规则,对象会通过 multi-ref 序列化,允许对对象图表进行编码。
Document/Wrapped服务
这两种服务很类似,都不对数据进行 SOAP 编码,而只是简单的 XML Schema 。在这两种情况中, Axis 仍然对 java 表示与 XML 进行绑定,所以只需要处理 Java 对象,而不是直接处理 XML 结构。
下面是一个关于购买顺序的 SOAP 消息,用来说明两者的区别:
<soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 <soap:Body>
    <myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO">
      <item>SK001</item>
     <quantity>1</quantity>
      <description>Sushi Knife</description>
    </myNS:PurchaseOrder>
 </soap:Body>
</soap:Envelope>
PurchaseOrder 元素的 Schema 如下:
<schema targetNamespace="http://commerce.com/PO">
 <complexType name="POType">
    <sequence>
      <element name="item" type="xsd:string"/>
      <element name="quantity" type="xsd:int"/>
      <element name="description" type="xsd:string"/>
    </sequence>
 </complexType>
 <element name="PurchaseOrder" type="POType"/>
</deployment>
对于 Document 样式的服务,将会映射到一个如下的方法:
public void method(PurchaseOrder po)
也就是说,整个 <PurchaseOrder> 元素作为方法的一个单独的 bean 对象参数,这个 Bean 类应该有三个成员属性。而对于 wrapped 样式的服务来说,将会映射到如下的方法:
public void purchaseOrder(String item,int quality,String description)
注意在这种情况的大小写, <PurchaseOrder> 元素是一个 ”wrapper” ,只处理正确的操作。方法的参数就是 unwrap 外层元素后的每一个内层元素。
document 或者 wrapped 样式的定义是在 WSDD 中定义的:
<service ... style="document"> for document style
<service ... style="wrapped"> for wrapped style
当使用 WSDL 文档创建 Web Service 的时候,就不需要担心到底是哪种服务了。
Message服务
最后是 Message 样式的服务,当需要使 Axis 无效,将代码作为实际的 XML 查看而不是 java 对象的时候,就使用这种服务。
下面是四的 message-style 服务的方法的合法信号
public Element [] method(Element [] bodies);
public SOAPBodyElement [] method (SOAPBodyElement [] bodies);
public Document method(Document body);
public void method(SOAPEnvelope req, SOAPEnvelope resp);
前两个将方法的数组传给方法 DOM 元素或者 SOAPBody 元素的数组 ----- 这个数组包含 <soap:body> 中的每一个 XML 元素。
第三个方法传递一个 DOM 文档,这个文档表示 <soap:body> ,并期望同样的返回。
最后一个传递两个 SOAPEnvelope 对象来表示请求和响应消息,这意味着可以在服务方法中查看或者修改 headers
Message样例
Axis 的例子中, samples\message\MessageService.java 就是一个 Message 服务的例子,服务的类是 MessageService ,包含一个公开方法, echoElement ,符合上述中的第一个方法:
public Element[] echoElements(Element[] elems)
MsgProvider 是一个 handler ,它调用 echoElement() 方法,传递一个 org.w3c.dom.Element 的数组作为参数,作为输入信息的 SOAPbody 的直接子元素。一般来说,这个数组会包含一个单独的 Element( 可能是一个 XML 文档的根元素 ) ,但是 SOAP Body 可以处理任意多个子元素。这个方法返回一个 Element[] 数组作为响应消息的 SOAP Body
package samples.message ;
import org.w3c.dom.Element;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPElement;
/**
 * Simple message-style service sample.
 */
public class MessageService {
    /**
     * Service method, which simply echoes back any XML it receives.
     *
     * @param elems an array of DOM Elements, one for each SOAP body element
     * @return an array of DOM Elements to be sent in the response body
     */
    public Element[] echoElements(Element [] elems) {
        return elems;
    }
    public void process(SOAPEnvelope req, SOAPEnvelope resp) throws javax.xml.soap.SOAPException {
    SOAPBody body = resp.getBody();
    Name ns0 = resp.createName("TestNS0", "ns0", "http://example.com");
    Name ns1 = resp.createName("TestNS1", "ns1", "http://example.com");
    SOAPElement bodyElmnt = body.addBodyElement(ns0);
    SOAPElement el = bodyElmnt.addChildElement(ns1);
    el.addTextNode("TEST RESPONSE");
    }
}
MessageService WSDD 文件内容如下:
<deployment name="test" xmlns="http://xml.apache.org/axis/wsdd/"
      xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
      xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
         <service name="MessageService" style="message">
    <parameter name="className" value="samples.message.MessageService"/>
    <parameter name="allowedMethods" value="echoElements"/>
 </service>
</deployment>
注意这里使用的是 style=”message” ,而不是使用 provider=”java:RPC” message style 告诉 Axis 本服务是由 org.apache.axis.providers.java.MsgProvider 来处理的,而不是 org.apache.axis.providers.java.RPCProvider
6.XML<---->Java 数据映射
Java类型映射到SOAP/XML
互操作,或者叫 interop ,是各种 SOAP 实现之间的一个存在的挑战。如果期望服务在其他的平台和实现上也可以使用,需要理解这个概念。 Axis Java 类型到 WSDL/XSD/SOAP 的映射由 JAX-RPC 规范确定。相关内容请参考 JAX-RPC 规范。
WSDL Java 的标准映射
xsd:base64Binary          byte[]
xsd:boolean                     boolean
xsd:byte                             byte
xsd:dateTime                  java.util.Calendar
xsd:decimal                      java.math.BigDecimal
xsd:double                        double
xsd:float                             float
xsd:hexBinary                  byte[]
xsd:int                                  int
xsd:integer                         java.math.BigInteger
xsd:long                             long
xsd:QName                      javax.xml.namespace.QName
xsd:short                            short
xsd:string                            java.lang.String
如果在 WSDL 中声明了一个对象是 nillable 的,则调用者可以选择返回值为 0 ,这样的话,原始数据类型可以使用它们的包装类代替,例如 Byte Double Boolean
SOAP编码数据类型
XSD 数据类型相对应的是 SOAP ‘Section 5’ 数据类型,这些数据类型都是 nillable 的,所以总是可以和包装类映射。这些类型之所以存在是因为他们都支持 ID HREF 属性,所以也用于当一个 RPC 编码的 context 来支持 multi-ref 序列化。
7. 异常
一般来说, Axis java.rmi.RemoteException 映射成为 SOAP Fault 。这部分内容在笔者介绍的 Axis2 的文章中有比较详细的介绍,请参考。
8.Axis 可以 / 不可以通过 SOAP 发送的内容
Java 的集合框架元素,例如 Hashtable ,具有序列器,但是和其它的 SOAP 实现没有正式的交互操作能力,并且在 SOAP 规范中没有对应的复杂对象。最可靠的发送集合对象的办法就是使用数组。
没有预先注册的对象:不能发送任意的 Java 对象,并且期望它们可以被在服务器端被理解。在使用 RMI 的时候,可以发送和接受实现了 Serializable 接口的 Java 对象,那是由于双发都是使用 Java Axis 值可以发送那么被 Axis 序列器注册的对象。文本后面会介绍如何使用 BeanSerializer 来序列化任何符合 JavaBean 规范的类。
远程引用:远程引用 (Remote Reference) 既不是 SOAP 规范的一部分,也不是 JAX-RPC 的一部分,所以不能返回对象的引用,然后期望调用者可以使用它作为 SOAP 调用的参数或者其他调用的参数。此时应该使用其他的方案,例如将他们存储在 HashMap 中,使用数字或者字符串键值来进行标识,这样就可以传递键值。
9. 编码 Beans---BeanSerializer
Axis 具有序列化和反序列化的能力,不需要编写代码,任何 Java 类,主要它遵守标准 JavaBean 的模式,那么就只需要告诉 Axis Java 类与 XML Schema 类型之间的映射,配置方式如下:
<beanMapping qname=”ns:local” xmlns:ns=”someNamespace”
                   languageSecificType=”java:my.java.thingy”/>
<beanMapping> 标签将一个 Java 类映射到一个 XML QName 。主要它包含两个重要的属性, qname languageSpecificType 。所以在上例中,将 my.java.thingy 类映射到 XML QName:[someNamespace]:[local]
下面看一个例子: BeanService.java
package samples.userguide.example5;
public class BeanService
{
    public String processOrder(Order order)
    {
        String sep = System.getProperty("line.separator");
        String response = "Hi, " + order.getCustomerName() + "!" + sep;
        response += sep + "You seem to have ordered the following:" + sep;
        String [] items = order.getItemCodes();
        int [] quantities = order.getQuantities();
        for (int i = 0; i < items.length; i++) {
            response += sep + quantities[i] + " of item : " + items[i];
        }
        response += sep + sep +
                    "If this had been a real order processing system, "+
                    "we'd probably have charged you about now.";
        return response;
    }
}
上面的代码中, Order 类是一个 JavaBean 类。由于 Order 类不是一个基本类型,这样 Axis 就不能识别它,所以一个错误的 wsdd 是下面这样的:
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    <service name="OrderProcessor" provider="java:RPC">
        <parameter name="className" value="samples.userguide.example5.BeanService"/>
        <parameter name="allowedMethods" value="processOrder"/>
    </service>
</deployment>
而正确的 wsdd 文件应该为下面的文件:
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    <service name="OrderProcessor" provider="java:RPC">
        <parameter name="className" value="samples.userguide.example5.BeanService"/>
        <parameter name="allowedMethods" value="processOrder"/>
        <beanMapping qname="myNS:Order" xmlns:myNS="urn:BeanService" languageSpecificType="java:samples.userguide.example5.Order"/>
    </service>
</deployment>
运行的结果如下:
此时在 Client 类中需要添加如下的代码:
QName    qn      = new QName( "urn:BeanService", "Order" );
call.registerTypeMapping(Order.class, qn,new org.apache.axis.encoding.ser.BeanSerializerFactory(Order.class, qn), new org.apache.axis.encoding.ser.BeanDeserializerFactory(Order.class, qn));
Axis 允许用户编写自定义的序列器和反序列器,并提供了实现序列器和反序列器的工具。现在只需要查看 DataSer/DataDeser 类、 BeanSerializer/BeanDeserializer ArraySerializer/ArrayDeserializer 以及 org.apache.axis.encoding.ser 包中的其他类。
部署自定义的映射 ----<typeMapping> 标签
在建立了自定义的序列器和反序列器后,需要告诉 Axis 这些序列器的应用范围,通过在 WSDD 中使用它:
<typeMapping qname="ns:local" xmlns:ns="someNamespace"
             languageSpecificType="java:my.java.thingy"
             serializer="my.java.Serializer" 获取序列器的序列器工厂类
             deserializer="my.java.DeserializerFactory" 、、
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
实际上 <beanMapping> <typeMapping> 的一个简化,其中 serializer=”org.apache.axis.encoding.ser.BeanSerializerFactory”,deserializer=”org.apache.axis.encoding.ser.BeanDeserializerFactory”,encodingStyle=”http://schemas.xmlsoa.org/soap/encoding”
<arrayMapping qname="ns:ArrayOfthingy" xmlns:ns="someNamespaceURI"
             languageSpecificType="java:my.java.array.thingy[]"
                             innerType="ns2:thingy" xmlns:ns2="anotherNamespaceURI" 数组的元素类型
             encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值