SOAP净化有线协议(二):Apache SOAP介绍(2)

apache

三、带有JavaBean的HelloWorld实例
如前所述,Apache SOAP提供了许多预先构造的串行化和反串行化方法,其中包括为利用Java Vector、Enumeration、数组、JavaBean作为参数和返回值而提供的串行化器和反串行化器。在这一部分,我将修改HelloWorld服务,通过一个JavaBean传入接收Hello信息的用户名。

3.1、HelloWorld服务
改写后的HelloWorld服务完整代码如下:

package hello;
public class HelloServer
{
public String sayHelloTo(String name)
{
System.out.println("sayHelloTo(String name)");
return "Hello " + name + ", How are you doing?";
}
public String sayHelloTo(Name theName)
{
System.out.println("sayHelloTo(Name theName)");
return "Hello " + theName.getName() + ", How are you doing?";
}
}
服务的代码仍旧很简单,仍旧类似于不用JavaBean时的HelloWorld服务。不过,这意味着最复杂的工作都转移到了客户端。事实上,这个版本的服务与以前版本的唯一差别在于,现在出现了一个重载的sayHelloTo()方法。上面的代码中重载后的方法用粗体字显示。

重载的方法需要一个对Name JavaBean的引用。Name JavaBean的定义如下:

package hello;
public class Name
{
private String name;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
3.2、部署服务
部署一个使用了JavaBean的服务时,需要为Apache SOAP服务器提供一些额外的信息。因此,现在部署服务的过程稍微复杂一点。

■ 使用管理工具部署服务

要使用管理工具部署这个新版的HelloWorld服务,首先按照前面所介绍的步骤进行,但这一次不要点击Deploy按钮。现在,在Number of Mappings输入框输入1,它表示我们将给出一个映射(即Name JavaBean)的信息。紧接Mappings之下有一个表格,我们要用到这个表格的第一行。保留Encoding Style的值为SOAP,把NameSpace URI设置成对象的ID:在本例中,它是urn:Hello。接下来,把Local Part和Java Type输入框设置成Name JavaBean的完整名字,即hello.Name。最后,把Java to XML Serializer和XML to Java Deserializer输入框设置成org.apache.soap.encoding.soapenc.BeanSerializer,这是一个实现了Serializer和Deserializer接口的类,用来串行化和反串行化Name JavaBean。如果你用到了更多的JavaBean(比如还有一个Address Bean),则应该在这个表格中输入其他Bean的信息,同时还应该更新Number of Mappings输入框的值,使之反映出表格中实际被使用的行数。

■ 从命令行部署服务

要从命令行进行部署,我们只需修改作为命令行参数传入的XML部署描述器文件。修改后的XML文件如下所示:

<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:Hello">
<isd:provider type="java" scope="Application" methods="sayHelloTo">
<isd:java class="hello.HelloServer" static="false"/>
</isd:provider>
<isd:mappings>
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="urn:Hello" qname="x:hello.Name"
javaType="hello.Name"
java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializer"
xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializer"/>
</isd:mappings>
</isd:service>
正如在前一个例子中,这些XML代码所包含的信息和通过Web界面的管理工具所提供的信息一样。

3.3、HelloWorld客户程序
和第一个例子一样,客户程序更复杂,也更令人感兴趣。这里我不再仔细分析整个客户程序,而是介绍两个客户程序版本的不同之处。由于调用方法的一个参数(在本例中,它是唯一的参数)是一个JavaBean,所以必须手工设置一个类型映射注册项。这个任务通过如下步骤完成:先创建org.apache.soap.encoding.SOAPMappingRegistry类的一个实例,然后调用它的mapTypes()方法。正如mapTypes()方法名字所预示的,它用来注册一个以前未知的类型,比如定制的JavaBean。mapTypes()方法的参数包括要使用的编码方式、限定的JavaBean名字、类型的完整类名、串行化器和反串行化器。在本例中,执行串行化任务的是标准的Bean串行化器。限定的JavaBean名字包含一个元素的名字,包括它所属的名称空间。在本例中,Name JavaBean的限定名字由名称空间URI(urn:Hello)和本地名字(hello.Name)结合构成。请看下面的代码片断:

// 创建类型映射注册器
SOAPMappingRegistry smr = new SOAPMappingRegistry();
BeanSerializer beanSer = new BeanSerializer();
// 映射类型
smr.mapTypes(Constants.NS_URI_SOAP_ENC,
new QName("urn:Hello", "hello.Name"),hello.Name.class, beanSer, beanSer);
接下来,客户程序必须告诉Call对象使用新的注册器而不是默认的注册器。为此,我们要调用Call对象的setSOAPMappingRegistry()方法,如下所示:

call.setSOAPMappingRegistry(smr);
手工设置好类型映射注册器之后,接下来还必须为Call对象设置参数。这一步骤可以按前面介绍的方法完成,不同之处在于,现在我们不再用字符串类型的名字作为参数,而是用JavaBean作为参数,如下所示:

// 设置调用参数
Vector params = new Vector();
Name theName = new Name();
theName.setName(name);
params.addElement(new Parameter("name", hello.Name.class, theName, null));
call.setParams(params);
客户程序剩下的部分和原来的版本一样。Listing 3显示了完整的客户程序代码:

Listing 3: Client2.java
package hello;
import java.net.URL;
import java.util.Vector;
import org.apache.soap.SOAPException;
import org.apache.soap.Constants;
import org.apache.soap.Fault;
import org.apache.soap.rpc.Call;
import org.apache.soap.rpc.Parameter;
import org.apache.soap.rpc.Response;
import org.apache.soap.encoding.SOAPMappingRegistry;
import org.apache.soap.encoding.soapenc.BeanSerializer;
import org.apache.soap.util.xml.QName;

public class Client2
{
public static void main(String[] args) throws Exception
{
if(args.length == 0)
{
System.err.println("Usage: java hello.Client [SOAP-router-URL] ");
System.exit (1);
}
try
{
URL url = null;
String name = null;
if(args.length == 2)
{
url = new URL(args[0]);
name = args[1];
}
else
{
url = new URL("http://localhost:8080/apache-soap/servlet/rpcrouter");
name = args[0];
}
// 构造调用对象
Call call = new Call();
call.setTargetObjectURI("urn:Hello");
call.setMethodName("sayHelloTo");
call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
// 创建类型映射注册器
SOAPMappingRegistry smr = new SOAPMappingRegistry();
BeanSerializer beanSer = new BeanSerializer();
// 映射类型
smr.mapTypes(Constants.NS_URI_SOAP_ENC,
new QName("urn:Hello", "hello.Name"),
hello.Name.class, beanSer, beanSer);
call.setSOAPMappingRegistry(smr);
// 设置参数
Vector params = new Vector();
Name theName = new Name();
theName.setName(name);
params.addElement(new Parameter("name", hello.Name.class,
theName, null));
call.setParams(params);
// 发出调用
Response resp = null;
try
{
resp = call.invoke(url, "");
}
catch( SOAPException e )
{
System.err.println("Caught SOAPException (" +
e.getFaultCode() + "): " + e.getMessage());
System.exit(-1);
}

// 检查应答
if( !resp.generatedFault() )
{
Parameter ret = resp.getReturnValue();
Object value = ret.getValue();
System.out.println(value);
}
else
{
Fault fault = resp.getFault();
System.err.println("Generated fault: ");
System.out.println (" Fault Code = " + fault.getFaultCode());
System.out.println (" Fault String = " + fault.getFaultString());
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
四、编译和运行程序
现在整个程序的开发工作已经完成,该是运行它的时候了。不过,我们首先要编译服务程序和客户程序。

创建一个hello目录,把Client1.java、Client2.java和HelloServer.java复制到这个目录。我把hello目录放到了Apache SOAP的示例目录(即E:\soap-2_0\samples)之下。编译程序时,classpath中只需包含hello目录的父目录(即E:\soap-2_0\samples)、soap.jar和xerces.jar。我用下面的批命令编译程序:

set CLASSPATH=E:\soap-2_0\samples\;E:\soap-2_0\lib\soap.jar;E:\xerces-1_2_0\xerces.jar
javac -d .. HelloServer.java Client.java Client2.java
注意:从hello目录执行这个批命令文件。

要使用这个服务,除了部署它之外,还需要修改Web服务器的classpath,确保Web服务能够找到hello.HelloServer类——对于本例,这是指把E:\soap-2_0\samples加入到Web服务器的classpath。对classpath进行必要的修改之后,重新启动Web服务器。接下来就可以运行客户程序了。下面是我运行hello.Client的批命令文件:

set CLASSPATH=E:\soap-2_0\samples\;E:\soap-2_0\lib\soap.jar;E:\xerces-1_2_0\xerces.jar
java hello.Client Tarak
这里的classpath和编译程序时用的classpath相同。

最后,运行hello.Client2的批命令文件可以如下:

set CLASSPATH=E:\soap-2_0\samples\;E:\soap-2_0\lib\soap.jar;E:\xerces-1_2_0\xerces.jar
java hello.Client2 Tarak
观察Web服务器的控制台窗口,看看在运行两个不同的客户程序时,HelloWorld服务的哪些方法正在被调用。

■ 结束语
在这篇文章中,我介绍了如何用Apache SOAP实现来创建简单的基于SOAP的服务。在SOAP实现方面,另一个重要的竞争者是Microsoft。遗憾的是,“纯”Java开发者在使用Microsoft实现的时候会有一段艰苦的时光,因为它的实现包含了COM对象。

在下一篇文章中,我将介绍Apache SOAP支持的另一种创建服务的方式:使用JavaScript之类的脚本语言,而不是Java。另外,我还要介绍一个很不错的JavaScript引擎,即Rhino。
■ 参考资源

  • W3C的SOAP 1.1规范:
    http://www.w3.org/TR/SOAP/
  • 下载Apache SOAP:
    http://xml.apache.org/dist/soap/
  • 有关IBM SOAP工程的更多信息:
    http://www.alphaworks.ibm.com/tech/soap4j
  • Apache SOAP可用功能的一个清单:
    http://xml.apache.org/soap/features.html
  • Apache许可协议:
    http://www.apache.org/LICENSE.txt
  • 下载Tomcat 3.1
    http://jakarta.apache.org/builds/jakarta-tomcat/release/v3.1.1/bin/
  • 下载Apache Xerces 1.2版本:
    http://xml.apache.org/dist/xerces-j/
  • "MS SOAP SDK vs IBM SOAP4J: Comparison & Review," James Snell (O'Reilly):
    http://windows.oreilly.com/news/soapreview_0600.html
时间: 2024-09-12 05:13:04

SOAP净化有线协议(二):Apache SOAP介绍(2)的相关文章

SOAP净化有线协议(三):用脚本语言编写服务

脚本 你是一个渴望永远站在技术最前沿的Java开发者吗?软件产业风云变幻,你渴望把握Web的未来,更重要的是,如何把自己数年的Java经验发挥到极致.要寻找这些问题的答案,你不必走得太远,答案就在于SOAP. SOAP(简单对象访问协议)是一种利用XML编码数据的有线协议,它为Java的平台无关性.可移植性带来了更高层次的协同操作能力.在这个关于SOAP的系列文章的第二篇中,我介绍了Apache SOAP.作为SOAP规范的实现之一,Apache SOAP简化了SOAP应用的构造.我们曾经用Ap

SOAP净化有线协议(四):简化客户程序

程序 Java 2平台1.3版本为Java映像API(Reflection API)增加了一个极其实用的扩展:动态代理类.一个动态代理类就是一个实现了一系列运行时指定的接口的类.这个代理可以象它真正实现了这些接口一样使用.换句话说,可以直接在代理对象上调用任意接口的任意方法--当然,必须先进行必要的类型定型(casting).由此,我们可以用动态代理类为一组接口创建一个类型安全的代理对象,且不必象使用编译时工具一样预先生成代理(有关动态代理类更详细的说明,请参见本文最后的参考资源). 接下来我将

Apache SOAP的Web Services在Tomcat4.0.4的安装和测试

apache|services|web 相关下载: Apache SOAP http://xml.apache.org/soap/index.html Tomcat4.0.4 http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.4/ 1.安装Apache SOAP到C盘根目录,即C:\soap-2_3_1 2.安装Tomcat4.0.4到C:\Program Files\Apache Tomcat 4.0 3.复制C:

HOW TO: BETA: Integrate a .NET Client with an Apache SOAP 2.2 XML Web Service

apache|client|web|xml HOW TO: BETA: Integrate a .NET Client with an Apache SOAP 2.2 XML Web Service --------------------------------------------------------------------------------The information in this article applies to: Microsoft Visual Studio .N

简单SOAP客户机:通用Java SOAP客户机

SOAP(简单对象访问协议)是 IBM.Microsoft.DevelopMentor 和 UserLand Software 为在网络上交换信息而开发的一种已在发展的 W3C 标准.随着 Web 上 可以公开使用的 SOAP 服务器的不断增加,SOAP 几乎对用任何语言编写的程序― ― 即使是用流行的简单语言(如 Visual Basic.JavaScript 和 perl)编写的 非常短小的程序――执行着 HTML 对 Web 浏览器所做的事:它为这些程序提供一 个简单的方法来利用万维网上不

有线电视电缆(Cable)方式宽带接入介绍

有线电视电缆(Cable)方式宽带接入互联网的标准是DOCSIS(Data Over Cable Service Interface Specification),最近这个标准升级到了2.0,并且Imedia公司在4月份宣布了DOCSIS2.0芯片IM6030和可立即批量生产的参考设计.这意味着新型Cable猫和头端设备的上市时间会大大加快,成本也能保证较低水平,这对Cable宽带接入市场的发展是至关重要的. 改进上行传输速率 新版DOCSIS 的主要改进是大大提高了上行信道速率,可达到30Mb

Python远程桌面协议RDPY安装使用介绍_python

RDPY 是基于 Twisted Python 实现的微软 RDP 远程桌面协议. RDPY 提供了如下 RDP 和 VNC 支持: ●RDP Man In The Middle proxy which record session ●RDP Honeypot ●RDP screenshoter ●RDP client ●VNC client ●VNC screenshoter ●RSS Player 目前能够找到的关于RDPY的中文介绍确实很少,自己也是没有进行很深入的研究,这里就先记录一下安

互联网协议入门详解介绍

一.概述 1.1 五层模型 互联网的实现,分成好几层.每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持. 用户接触到的,只是最上面的一层,根本没有感觉到下面的层.要理解互联网,必须从最下层开始,自下而上理解每一层的功能. 如何分层有不同的模型,有的模型分七层,有的分四层.我觉得,把互联网分成五层,比较容易解释. 如上图所示,最底下的一层叫做"实体层"(Physical Layer),最上面的一层叫做"应用层"(Application Layer),中间的三

Apache Gora介绍

介绍         Gora是一个开源的ORM框架,主要为大数据提供内存数据模型与数据的持久化.目前Gora支持对于列数据.key-value数据,文档数据与RDBMS数据的存储,还支持使用Apache Hadoop来对对大数据进行分析 特点             虽然目前市面上有很多不错的关系数据库的ORM框架,但是基于数据模型的框架如JDO还是有一些不足,如对于列数据模型的存储与持久化.Gora正好弥补了这个问题,它能使用户很容易对大数据时行 内存建模与持久化,而且支持Hadoop来对大