- 浏览: 303868 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (271)
- jBPM (0)
- WebService (10)
- Flex (0)
- RubyOnRails (1)
- Java (56)
- J2EE (2)
- SQL (5)
- Tapestry (2)
- Dom4j (1)
- Japanese (9)
- English (4)
- JavaScript (3)
- Ajax (12)
- MyDiary (3)
- Log4j (2)
- XML (3)
- UML (1)
- Struts (3)
- Others (8)
- Funny (7)
- ProjectManagement (3)
- Tomcat (1)
- Servlet&Jsp (6)
- Html (4)
- iBATIS (1)
- EasyMock (1)
- Astronomy (1)
- Biology (1)
- Food and Health (0)
最新评论
-
yet8telecom:
good
js数组 sort方法的分析 转自NorthSnow HOME -
imain:
最后的结果是:1,5,3,4,6,2
js数组 sort方法的分析 转自NorthSnow HOME -
lixiaoqing:
最后一个输出结果应该是3,5,1,4,2,6 吧?
js数组 sort方法的分析 转自NorthSnow HOME -
benxiaohai1212:
请问如果输入参数是数组array类型,怎么处理?谢谢!
实例讲解:JAVA SOAP技术 -
netdisk:
这个建议可以用在电子文档管理上
软件文档管理指南
Java 2平台1.3版本为Java映像API(Reflection
API)增加了一个极其实用的扩展:动态代理类。一个动态代理类就是一个实现了一系列运行时指定的接口的类。这个代理可以象它真正实现了这些接口一样使
用。换句话说,可以直接在代理对象上调用任意接口的任意方法——当然,必须先进行必要的类型定型(casting)。由此,我们可以用动态代理类为一组接
口创建一个类型安全的代理对象,且不必象使用编译时工具一样预先生成代理(有关动态代理类更详细的说明,请参见本文最后的参考资源)。
接下来我将介绍一个以动态代理类为基础的框架,这个框架使得SOAP(简单对象访问协议)客户程序的创建更加简单和直观。SOAP是一种用XML编码数据
的有线协议。在本系列文章的第二篇、第三篇构造SOAP服务的过程中,我们发现客户程序的开发者必须多做许多原来不必做的工作。为帮助回忆,你可以看一下
第二篇文章中的SOAP服务代码,看看和客户程序代码相比较时,服务程序的SOAP代码是多么微不足道。本系列文章前几篇所创建的简单SOAP服务显示
出,基于SOAP的服务只包含无论用不用SOAP都必须提供的代码。服务程序的开发者要编写的额外代码很少,而客户程序开发者却有许多额外工作要做。本文
介绍的类将把这些额外工作减到最少。
一、介绍SOAP代理类
首先,我要给出如果客户程序使用了本文创建的框架,它将变成什么样子:
package hello; import soapproxy.*; public class Client { public static void main(String[] args) { try { Class[] interfaces = new Class[] {hello.Hello.class}; Hello hello = (Hello)(Proxy.newInstance("urn:Hello",interfaces)); // 调用sayHelloTo方法 // 调用sayHelloTo方法 |
也许是出于我的个人爱好,我认为上面的客户代码比第二篇和第三篇文章中的客户代码更好。如果你现在不能理解上面的代码,这很正常,但我想待到本文结束时你会理解的。
要理解客户程序的代码,你必须深入了解SOAP
Proxy类,它在soapproxy包内,可以在Proxy.java内找到(参见本文最后的参考资源)。Proxy类有一个私有的构造函数,它意味着
Proxy实例不能从Proxy之外创建;新建Proxy实例的唯一方法是通过静态的newInstance()方法。newInstance()方法有
两个参数:SOAP服务的对象ID,以及一个数组,数组中包含一组该代理要实现的接口的名字。对象ID很简单,但这些接口名字是什么?从哪里去得到这些接
口的名字?SOAP服务的开发者直接把服务上所有可被客户程序调用的方法堆在一起得到一个接口。相当简单,不是吗?
现在我们为HelloWorld服务定义一个接口。第二篇文章中,这个服务的最终版本有sayHelloTo()方法的两个重载版本:一个版本的参数是一
个字符串,另一个版本的参数是一个Name JavaBean。这两个方法就可以构成一个接口,称为Hello,如下所示:
package hello; public interface Hello { public String sayHelloTo(String name); public String sayHelloTo(Name name); } |
服务开发者决定要创建多少接口,以及为这些接口取什么样的名字。例如,你可以为HelloWorld服务创建两个接口,每一个接口包含一个方法。一般地,
你应该避免创建方法数量大于七个的接口。另外,注意只把那些看来有必要放在一起的方法用一个接口组织起来。例如,如果HelloWorld服务还有一个返
回定制的Good-Bye消息给调用者的sayByeTo()方法,设计两个独立的接口也许比较明智:一个接口用于sayHelloTo()方法,一个接
口用于sayByeTo()方法。
现在我们有了定义HelloWorld服务和客户程序之间契约的接口,下面返回来看newInstance()方法。如前所
述,newInstance()方法创建Proxy类的一个新实例。newInstance()方法可以创建新实例是因为它属于Proxy类,能够访问私
有的构造函数。newInstance()方法为新创建的实例调用initialize()方法。initialize()值得关注,因为动态代理就是在
这里创建和返回。initialize()的代码如下所示:
private Object initialize(Class[] interfaces) { return(java.lang.reflect.Proxy.newProxyInstance(getClass().getClassLoader() ,interfaces,this)); } |
注意newProxyInstance()方法的应用。创建动态代理类实例的唯一办法是调用该类(即java.lang.reflect.Proxy类)
静态的newProxyInstance()方法。java.lang.reflect.Proxy类为创建动态代理类提供了静态方法,而且它还是所有由
这些方法创建的动态代理类的超类。换句话说,它不仅是一个创建动态代理类的工厂,而且它本身也是一个动态代理类!因此,在我们的例子中,SOAP代理不是
动态代理;相反,这个动态代理实际上是newProxyInstance静态方法返回的java.lang.reflect.Proxy类的一个实例。从
本文后面可以看到,这个动态代理实际上通过SOAP代理实现的invoke()方法完成它的所有工作。那么,这个动态代理如何建立和SOAP代理的联系
呢?因为有一个对SOAP代理的引用传递给了newProxyInstance()方法。也许现在这听起来有点费解,但只要你分析一下invoke()方
法,这一切就很明白了。
java.lang.reflect.Proxy类构造函数的第一个参数是一个类装载器实例,第二个参数是需要动态实现的接口的数组(它就是客户程序传递
给newInstance()的数组),第三个参数是一个实现了java.lang.reflect.InvocationHandler接口的类的实
例。因为SOAP
Proxy类实现了InvocationHandler接口,所以第三个参数是代理实例本身(即this)。InvocationHandler接口有一
个方法invoke()。当动态代理的动态实现的接口被调用时,Java运行时环境调用invoke()方法。因此,举例来说,当客户程序调用动态代理的
Hello接口的sayHelloTo()方法时,Java运行时环境将调用SOAP代理的invoke()方法。
你可能已经发现,SOAP代理的newInstance()方法不返回SOAP代理的实例;相反,它返回newInsance()刚刚创建的动态代理,而
动态代理动态地实现客户程序传入的接口数组。客户程序可以将这个返回的动态代理定型为传入newInstance()的任意接口类型,在动态代理上调用接
口所定义的各个方法,就象动态代理真地实现了那些接口一样。
. . try { Class[] interfaces = new Class[] {hello.Hello.class}; Hello hello = (Hello)(Proxy.newInstance("urn:Hello",interfaces)); // 调用参数为字符串的sayHelloTo方法 System.out.println(hello.sayHelloTo("John")); // 调用参数为Name JavaBean的sayHelloTo方法 Name theName = new Name(); theName.setName("Mala"); System.out.println(hello.sayHelloTo(theName)); } . . |
在上面的代码中,invoke()方法将被调用两次,每次调用sayHelloTo()方法时执行一次。现在我们来看看invoke()方法。简而言
之,invoke()方法的工作正是第二篇文章中每一个客户程序必须手工完成的工作,其中包括:用合适的调用参数设置一个Call对象,定制的调用参数所
需要的类型映射。由于SOAP代理中的invoke()方法担负了所有这些任务,客户程序释放了这份负担。
在invoke()方法接收到的三个参数中,我们只对后面两个感兴趣。第二个参数,即Method对象,给出了被调用方法的名字。记住,被调用方法的名字
对应着一个SOAP服务导出的已知方法。服务的对象ID作为参数传递给newInstance()方法,所以invoke()方法已经拥有该对象ID。
invoke()方法利用这些信息,按照如下方式设置Call对象:
Call call = new Call(); call.setTargetObjectURI(urn); call.setMethodName(m.getName()); call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC); |
现在要做的是为远程服务调用设置参数。为此,我们要用到invoke()方法的第三个参数:传入动态代理上被调用方法的一个参数数组。数组中索引为0的参
数是方法调用中最左边的参数,索引为1的参数是方法的第二个参数,依此类推。举例来说,如果客户程序调用了sayHelloTo(String
name)方法,那么参数数组就是包含一个字符串的数组。invoke()方法处理该数组的每一个元素,创建一个由Parameter对象构成的向量
(Vector)(正如第二篇文章中客户程序所做的那样):
java.util.Vector params = new java.util.Vector(); for( int i=0; i<args.length; i++ ) { if( isSimple(args[i]) || isSimpleArray(args[i]) ) { params.add(new Parameter(_paramName+(i+1), args[i].getClass(),args[i],null)); } else if( isVector(args[i]) ) { addMapping((java.util.Vector)args[i]); params.add(new Parameter(_paramName+(i+1),args[i].getClass(),args[i],null)); } // 如果这个数组的元素不属于Java基本数据类型 // 则假定这是一个JavaBean的数组 else if( isArray(args[i]) ) { if( smr == null ) smr = new SOAPMappingRegistry(); if( beanSer == null ) beanSer = new BeanSerializer(); ArraySerializer arraySer = new ArraySerializer(); |
invoke()方法用到了许多私有的辅助方法,比如用isSimple()来确定参数的类型。如果参数是一个JavaBean或者一个数组,那么,程序
必须设置一个定制的SOAP映射注册项,并通过setSOAPMappingRegistry()方法对Call对象作相应的设置(参见第二篇文章)。
SOAP代理假定,当出现JavaBean时,SOAP服务用到的所有JavaBean按照如下方式映射:NameSpace
URI设置成对象ID,Local
Part设置成JavaBean完整的类名。我们部署HelloWorld服务时正是按照这个要求进行,所以一切都不存在问题。
invoke()方法的剩余部分相当简单:设置Call对象参数,设置定制SOAP映射注册项(如果有必要的话),发出调用,接收方法调用的返回值。如下所示:
if( params.size() != 0 ) |
二、HelloWorld服务
下面是HelloWorld服务的完整代码。有似曾相识的感觉吗?
package hello; |
回忆一下,Name是一个简单的JavaBean,代码如下:
package hello; public class Name |
事实上,这里服务的代码与第二篇文章中的服务程序代码完全一样。对于服务开发者来说,唯一增加的工作是创建Java接口。部署服务的方法也和第二篇文章中
讨论的完全一样,所以这里我不再介绍。相同的地方还不止如此,编译和运行客户程序的方法也和第二篇文章介绍的一样。为什么有这么多相同之处呢?因为我们创
建的代理是一个非插入式的框架,它不会修改和干涉任何Apache SOAP部件的内部工作——无论是客户端还是服务端。
三、其他说明
本文讨论的SOAP代理(可以从文章后面下载)支持以下参数类型:
⑴ 下面的Java基本数据类型及其对应的对象形式。
boolean, Boolean, |
注:服务器端总是接收基本数据类型。
⑵ 任何JavaBean
注:
注:
■ 结束语
在这个四篇文章构成的系列中,我不仅介绍了SOAP的基础知识,而且介绍了SOAP 1.1标准的一个优秀的实现:Apache SOAP。在本文中,我提供了一个以动态代理类为基础的框架,这个框架极大地简化了使用Apache SOAP的客户程序开发者的工作。
我深切地感到SOAP有着美好的前景,至少有两个理由使我这么认为:首先,SOAP以一些开放的标准为基础,比如XML。这使得无论是 Microsoft,还是反Microsoft的企业,都广泛地接受了SOAP。对于开发者来说,这无疑是一个天大的好消息。第二,SOAP正在成为其他 许多标准的基础,比如UDDI(Universal Description,Discovery,and Integration)。许多人认为,Web服务代表着下一代的Web应用开发,而SOAP和UDDI都是Web服务的关键组成部分。
■ 参考资源
发表评论
-
实例讲解:JAVA SOAP技术
2008-07-09 22:48 5715开始之前,我想就本文即将讨论的主题和读者需要具备的起点 ... -
开发 Web 服务,第 3 部分: SOAP 互操作性
2008-07-15 20:38 1022开发 Web 服务,第 3 部分: SOAP 互 ... -
Axis 1.2 RC3 在 tomcat 5.5.8下的配置
2008-07-09 22:50 1123Axis 1.2 RC3 在 tomcat 5.5.8下的配置 ... -
JDK tomcat Axis的安装及使用
2008-07-09 22:56 2696一.简介 什么是SOAP?SOAP是一个应用程序间的基于XML ... -
使用 WSDL 部署 Web 服务: 第 1 部分
2008-07-15 20:30 1109使用 WSDL 部署 Web 服务: 第 1 部 ... -
使用 WSDL 部署 Web 服务,第 2 部分: 简单对象访问协议(SOAP)
2008-07-15 20:33 1388使用 WSDL 部署 Web 服务,第 2 部分 ... -
SOAP净化有线协议(一):SOAP基础知识
2008-10-28 18:32 1783许多开发者都遇到过 ... -
SOAP净化有线协议(二):Apache SOAP介绍
2008-10-28 18:33 1984SOAP(简单对象访问 ... -
SOAP净化有线协议(三):用脚本语言编写服务
2008-10-28 18:34 1608你是一个渴望永远站在技术最前沿的Java开发者吗?软件产业风 ...
相关推荐
XML标签`<soap:Envelope>`用于声明SOAP Envelope的开始,而`</soap:Envelope>`标记其结束。 2. **SOAP Header**:可选部分,用于提供元数据,如安全性、路由信息或交易上下文。Header中的元素是可扩展的,可以包含...
SOAP(Simple Object Access Protocol)是一种基于XML的网络通信协议,用于在Web服务中交换结构化和类型化的信息。它允许应用程序通过HTTP等简单协议来发送和接收数据,从而实现跨平台、跨语言的通信。在“SOAP数据...
SOAP允许应用程序通过HTTP(Hypertext Transfer Protocol)和其他传输协议交换数据,这使得它成为构建分布式系统和服务的理想选择。在本文中,我们将深入探讨SOAP协议的核心概念、结构以及其在实际应用中的作用。 1...
### SOAP:XML跨平台Web Service开发技术 #### 1. 简介 SOAP(Simple Object Access Protocol),即简单对象访问协议,是一种用于交换结构化信息的标准协议。它是Web服务中用于远程过程调用的主要协议之一,特别是...
SOAP(Simple Object Access Protocol)是一种基于XML的协议,主要用于在分散或分布式的网络环境中交换结构化和类型化的信息。SOAP协议的设计目标是简单性和可扩展性,因此它并不包含传统消息系统和分布式对象系统的...
**SOAP(Simple Object Access Protocol)** 是一种基于 XML(Extensible Markup Language)的通信协议,它的设计目的是为了在分布式环境中提供轻量级的信息交换机制。SOAP 允许应用程序通过 HTTP(Hypertext ...
- **简单性**:SOAP协议的目的是简化分布式系统之间的通信,避免复杂的分布式对象系统特性。 - **可扩展性**:允许添加新的功能和扩展,而不影响基础协议的稳定性。 在SOAP消息的示例中,我们可以看到XML被用来创建...
### SOAP协议详解 #### 一、SOAP协议简介 SOAP(Simple Object Access Protocol)是一种轻量级的协议,用于实现分布式环境中不同系统之间的交互。它的主要特点是使用XML作为数据编码格式,这种选择使得SOAP具备跨...
SOAP(Simple Object Access Protocol)是一种基于XML的协议,主要用于在分散或分布的环境中交换结构化和类型化的信息。它的设计目标是简单性和可扩展性,因此它不包含一些传统消息系统和分布对象系统中的特性,如...
对于soap调用的测试程序 只需要编辑soap串即可调用测试
### SOAP协议规范详解 #### 一、SOAP协议概述 SOAP(Simple Object Access Protocol)协议是一种基于XML的标准协议,用于在分散或分布环境中交换结构化和类型化的信息。它旨在为不同平台之间的通信提供一个轻量级...
【SOAP 简要描述】 简单对象访问协议(SOAP,...总的来说,SOAP作为Web服务的标准通信协议,提供了灵活且标准化的方式来交换结构化信息,它简化了不同系统间的互操作性,并且在各种网络协议和编程语言之间架起了桥梁。
它通常包含`<soap:Envelope>`标签。 - **Header**:可选部分,用于传递与消息处理相关的附加信息,如认证、路由指令等。它由`<soap:Header>`标签表示。 - **Body**:必需部分,包含了SOAP消息的主要内容,即实际的...
<soap:Header/> <soap:Body> <Add xmlns="http://tempuri.org/"> <intA>1 <intB>2 </soap:Body> </soap:Envelope> ``` 在这个例子中,Body内的`Add`操作表示一个加法请求,`intA`和`intB`是参数。 **iOS中...
### SOAP协议规范详解 #### 一、概述 SOAP(Simple Object Access Protocol)是一种基于XML的信息交换协议,旨在为分布式环境中不同应用之间的通信提供一种标准化的方法。该协议规范由多个部分组成,包括SOAP封装...
### 使用SOAP简化客户程序 SOAP协议的一个关键优点是它能够简化客户端编程。由于SOAP消息的结构化,客户端只需解析XML并调用相应的函数即可处理服务器的响应。同时,通过使用WSDL(Web服务描述语言),客户端可以...
SOAP(Simple Object Access Protocol)是一种基于XML的协议,它的全称是简单对象访问协议。SOAP设计的主要目的是在分散或分布式环境中提供一种轻量级、结构化的信息交换机制。SOAP协议不涉及具体的编程模型或特定...
SOAP(Simple Object Access Protocol)1.2是一种基于XML的协议,设计用于在分布式环境中实现结构化和类型化信息的平等交换。它强调简洁且轻量级的机制,使得不同系统间能够有效地通信。SOAP 1.2 包含四个主要组成...
### 浅谈SOAP协议 #### 一、为什么需要SOAP? 随着信息技术的发展,现代企业的信息化建设面临着日益复杂的挑战。为了应对这种复杂性,企业需要构建一套兼容性强、支持多平台、多系统的解决方案。这意味着信息系统...