引子:
关于SOAP其实我一直模模糊糊不太理解,这种模模糊糊的感觉表述起来是这样:
于是我详细查阅了网上的资料,结合自己的理解,归纳整理如下,引用部分过于零散,就未标示,还请谅解
要好好谈SOAP,就必须从其源头开始,它的源头就是WebServices(Web服务)
1.Web服务
最早的软件都是本地软件,只运行在本地电脑上,直到网络技术诞生它也只是利用网络传送资料,这之后网络技术独自发展网页WEB自己发展了好多年,直到大家发现网络技术不只是用来看看网页,还可以把网络技术更深地应用进本地软件中,深入地跟本地软件的功能结合,拓展本地软件的功能,Web服务的概念就是在这种环境下兴起的。
Web服务 简单地说,,就是服务器如何向客户端提供服务,现有的实现方式可以分为三类:
1.1.其他相关概念
RMI
2.SOA
SOA 是前几年炒的很火的一个词, 不亚于当前的 Cloud Computing , 如果说 RPC 是基于方法调用(method),那么 SOA 则是基于 消息, 基于方法调用通常会与特定的程序语言 耦合起来,而后者则与具体的实现语言无关, 所以在一定程度上得到大公司的支持
3.RPC
3.1总览:
3.2.实现方式:
3.3.其他相关概念
yar
yar是PRC的一个框架,类似webservice的,可以远程调用方法,返回的数据不单单是字符串,可以是数组等类型。
比方说,当你的项目非常庞大的时候,有些公用的模块就需要对外提供接口。
1、可以用curl方式调用,接口返回xml格式、或者json格式的字符串,调用方自己去解析。
2、可以用使用yar写的方法,直接返回结果,就跟调用代码本身的方法一样,可以返回字符串、数组等格式。
Web服务描述语言-WSDL
WSDL(Web Services Description Language)是描述web服务的,是描述怎样访问web服务的。WSDL是用来描述SOAP的,换句话说,WSDL 文件告诉你调用 SOAP 所需要知道的一切。WSDL也是一段xml。现在各个语言对wsdl的支持都很成熟,可以根据同一份wsdl文件生成自己语言的客户端。
为了创建一个用于描述Web服务的XML格式化文件,Web服务描述语言(WSDL)标准提供了足够多的细节,以便能够构建出客户端代码,从而访问服务或者服务器端代码以提供服务。一个服务的WSDL文件将会为你提供以下几个方面的内容:
2001 年3月,W3C推出了WSDL 1.1版本用于讨论,这并不是最终确定的规范。W3C Web服务描述工作组目前正在开发该规范的2.0版本,基本上已经到了尾声。虽然,WSDL通常是用于特定的SOAP服务,但是,从理论说,它是完全可以 用于特定的REST风格的GET或者POST操作的。
能够根据服务的WSDL描述来自动创建客户端和服务器端代码,支持这一功能的开发环境目前使用得很广泛,以便能够适用于Web服务器和Web服务客户端的 不同程序设计语言。如果你使用Google搜索“SOAP IDE”的话,大概会出现上百万条相关信息。也有这样的工具,根据Java或C#对象来生成相应的WSDL和代码。自动生成代码也许能够使你的开发效率更 高,但是离优化却是越来越远。
SOAP数据包结构解析
SOAP的消息被称为一个SOAP Envelope,包括SOAP Header和SOAP Body。其中,SOAP Header可以方便的插入各种其它消息来扩充Web Service的功能,比如Security(采用证书访问Web Service),SOAP Body则是具体的消息正文,也就是Marshall后的信息。
SOAP调用的时候,也就是向一个URL(比如 http://api.google.com/search/beta2 )发送HTTP Post报文(根据SOAP规范,HTTP Get报文也可被支持),调用方法的名字在HTTP Request Header SOAP-Action中给出,接下来就是SOAP Envelope了。服务端接到请求,执行计算,将返回结果Marshall成XML,用HTTP返回给客户端。
4.REST
4.1.概念:
4.1.推导REST
先从理论层次上我们看一下REST是怎么推导来的(参考论文第五章)
Web架构背后的设计基本原理,能够被描述为由一组应用于架构中元素之上的约束组成的架构风格。当将每个约束添加到进化中的风格时,会产生一些影响。通过检查这些影响,我们就能够识别出Web的约束所导致的属性。然后就能够应用额外的约束来形成一种新的架构风格,这种风格能够更好地反映出现代Web架构所期待的属性。通过简述REST作为架构风格的推导过程,后面各节将会详细描述组成REST风格的各种特定约束
0. 从“空”风格开始。从架构的观点来看,空风格描述了一个组件之间没有明显边界的系统,这就是我们描述REST的起点。
4.2.REST风格/约束:
Fielding 在他的论文中提出了一个RESTful应用应该具备的几点约束。
Fielding 认为,只有具备了上面的约束的应用才能算是REST应用,其实现在许多所谓的REST应用或服务,其实并不能算是真正的REST应用,目前很多所谓的REST应用,其实只是RPC而已。出现这样的情况很正常,因为RPC更符合一般程序员的思维。
之后这几个约束被表述为:
看了这几个特征后,你想起了什么? 你可能会破口而出:HTTP
HTTP是WWW的最核心的协议, 它将简单的分布于世界各个角落的资源都统一起来, 统一的地址, 简单的方法, 和一定数量的表达方式.(你可能对这三点描述很模糊,请go ahead).
REST 的三个要素就是是 唯一的资源标识, 简单的方法 (此处的方法是个抽象的概念), 一定的表达方式.
REST 是以 资源 为中心, 名词即资源的地址, 动词即施加于名词上的一些有限操作, 表达是对各种资源形态的抽象.
以HTTP为例,名词即为URI(统一资源标识), 动词包括POST, GET, PUT, DELETE等(还有其它不常用的2个,所以 整个动词集合是有限的), 资源的形态(如text, html, image, pdf等)
根据以上的描述,我们其实发现HTTP是一种典型的REST风格,这也难怪,在1994年提出REST风格时,REST被称作“HTTP对象模型”,但是那个名称常常引起误解,使人们误以为它是一个HTTP服务器的实现模型。这个名称“表述性状态转移”是有意唤起人们对于一个良好设计的Web应用如何运转的印象。反过来看HTTP就是REST的具体实现。在一个REST风格中,我们能够感受到的就是统一接口的数据,这些数据包括所以,当我们开发一个web服务时,比如一个网站,由于使用了HTTP(HTTPS)协议,其实就是一种REST风格,但是在这个REST风格中我们着重处理的是两点
1:URI,即所谓的资源,网站的uri设计
2:统一接口,即所谓的PUT,GET,POST,DELETE方法
虽然我们的网站是REST的风格的,但是由于统一接口设计的不好,导致我们网站在访问请求时,效率低下,以及可扩展性差。在深入浅出REST中,作者总结了五条关键原
1:为所有“事物”定义ID
2:将所有事物链接在一起
3:使用标准方法
4:资源多重表述
5:无状态通信
其中前四条就是对统一接口中的数据元素,第一二条讲的就是uri,第三四条讲的是控制数据。第五条无状态通信,这个需要特别说明下,无状态通信是指服务器和客户端通信是无状态的,假如我们的系统中使用Session保存客户端状态,这种情况就是非无状态通信,是一种unREST的方式。但是应用本身是有状态的,比如用户登录前后,就是应用状态的变化。
4.3.REST与WEB
Fielding指出,使用且符合代表性状态传输(REST)设计约束的 Web 上部署的组件,可以充分利用 Web 的有用特性,万维网(World Wide Web)才能够达到最佳的工作效果。可以这样理解REST——当一个浏览器得到并且显示构成HTML页面的各个元素时,它正在获取资源的当前状态的表现形式。在Fielding的博士论文中,他列举了REST风格的设计约束,并且解释了为什么这些约束能够充分利用Web 的有用特性,使其达到最佳状态,以及这些约束的关键所在。同时,在论文中,他也包含了一些关于REST和某些目前的Web风格之间 “不符合”的讨论,以及这些Web风格是如何导致设计无法利用Web特性的。
Fielding认为,对于使用HTTP承载应用程序协议穿越防火墙,XML-RPC 和SOAP所采用的方式是“从根本上被误导的概念。”它们所采用的方式违背了设立防火墙的概念,结果是,防火墙厂商为了保护系统需要侦察出所承载的协议。由于大多数SOAP应用程序使用HTTP都是为了穿越防火墙,因此,你可以发现REST与SOAP之间的冲突是从哪里开始的。Fielding认为,如果你打算使用HTTP的话,就应该与充分利用HTTP本身的含义。
REST风格强调,通过有限的操作或者是“动词”以及一个组件之间的标准接口,也就是HTTP协议提供的借口,来提升客户与服务之间的交互。通过为每一个资源分配其自己的URL,来实现灵活性,REST可以调用包含上百个URI的资源类型的客户,其中的关键是REST能够给你无限多的“名词”。REST使用HTTP的动词——简单的良定义操作集:POST, GET, PUT,DELETE进行请求和响应,从而避免了歧义。举个例子,GET只能够简单地返回资源的表现形式,而不能够创建任何其他的内容。
在Web发展的初期,由于人们都在试验通过收集各种不同来源的元素,从而把Web应用程序融合在一起,有大量这种Web服务的不成熟探索的例子——从HTTP页面中解析信息,用于页面创建者没有计划到的用途。这种“屏幕抓取”的Web类比表明,REST风格的方法是先于那些更加复杂的Web服务而出现的。
4.4.规划REST服务
在InfoQ上有一篇很好的文章来介绍如何规划REST服务《如何获取(GET)一杯咖啡——星巴克REST案例分析》,估计大家看完这篇文章,应该对如何规划REST服务会有更深的认识。
当我们要规划REST服务的时候,其中最关键的概念是“资源”。
资源是什么呢?广义上讲,任何事物只要有用,它就是资源。狭义的讲(在Web环境中),它是一个可以存放、连接在计算机上,可以通过比特流进行操控的实体。一个实体若要成为资源,它必须有一个URI。在这里URI包含了两重含义:1)它是该资源的名称 2)它是该资源的地址。
在规划URI的时候,有几点希望大家能够注意一下:
当我们定义好资源之后,接下来要做的事情就是定义操作资源的方法以及资源的表述格式了。
使用HTTP提供的基本方法来对资源进行操作,一般的操作定义如下:POST(创建资源)、GET(获取资源)、PUT(修改资源)、DELETE(删除)。它们正好对应了CRUD。
对资源的表述,一般的选择会是XML,但是我更加推荐使用JSON来表述资源。在网络中的传输量小,而且也便于JavaScript解析,同时使用其他语言解析也是非常方便的事情。不过,最关键的还是占用更少的资源,让同样的资源能够服务于更多的人。
4.5.一个简单的REST举例
假设我们希望一个Web服务暴露一部分目录,从这个目录中,用户将能够得到一些描述、图片、安装指令等等。为了得到数字“n1996-01”的描述,用户需要格式化一个GET请求,类似于下面的这个URL: http://company.com/catalog/description/n1996-01
在处理这个请求时,“/catalog”将映射到一个服务中,之后,通过该服务对“description/n1996-01”进行解释,从而 定位资源。在创建响应时,服务需要使用内容类型(Content-Type)的头文件来指定返回格式。在这种情况下,假定返回格式是HTML或者XML, 客户端能够使用它来控制页面的布局。如果要得到图片,那么这个请求将对“/catalog/picture/n1996-01”进行寻址,返回的响应将是 图片内容类型(Content-Type)。
4.6.REST的应用场景:
其实,我们经常容易犯的一个错误是:当我们了解了一个新的技术,就会用这个技术来解决所有的问题。有一句谚语是这么来说的:“在锤子的眼里,所有的东西都是钉子”,其实REST也只是我们工具箱里面的其中的一个工具而已,希望不要把它当做我们唯一的工具。下面,我们就来聊聊适合使用REST的应用场景和不适合使用REST的应用场景。
在我看来,REST最适合的应用场景是需要对外暴露服务的情况。此时,我们可以充分利用REST的自描述、无状态、唯一标识等特性来提供清晰、友好的API;此外,目前Jesery、RESTEasy等JAX-RS框架也提供了OAuth的支持,基本上能够保证服务安全。
最不适合的应用场景是对性能要求高的系统内部的服务调用,在这种情况下使用REST的话,那么REST所有的特性都会变成拖累。这个时候,还是需要选择更底层的通信协议和方式会更好一些,比如ICE。这样的错误,我曾经犯过,后来通过很长时间的努力才慢慢的将这个错误改过来。
4.7.RPC与REST的比较
如何选择?
根据笔者自己的经验和心得, 建议 能够使用REST就尽量使用REST, 主要基于下面几个考虑:
当然上述的几点也并非 RPC 都不满足,不过相对而言, REST 更加清晰和简洁, 再辅以 JSON 相应的服务会在性能和稳定性(简单通常意味着robust)方面有很大的提高.
总体上,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近REST风格的Web服务进行图书查找;雅虎提供的Web服务也是REST风格的。REST对于资源型服务接口来说很合适,同时特别适合对于效率要求很高,但是对于安全要求不高的场景。而SOAP的成熟性可以给需要提供给多开发语言的,对于安全性要求较高的接口设计带来便利。所以我觉得纯粹说什么设计模式将会占据主导地位没有什么意义,关键还是看应用场景,正是那句老话:适合的才是最好的
同时很重要一点就是不要扭曲了REST现在很多网站都跟风去开发REST风格的接口,其实都是在学其形,不知其心,最后弄得不伦不类,性能上不去,安全又保证不了,徒有一个看似象摸象样的皮囊。
4.8.soap与REST比较:
造成SOAP和REST放在一起讨论是因为,网络上很多工程师把REST风格和REST的实现混淆了。REST的概念比较宽泛,本身如果符合1)Client–server, 2)Stateless, 3)Cacheable, 4)Layered system, 和5)Uniform interface这几个主要的限制,就是RESTful的设计。同时呢,由于HTTP是一个很容易满足stateless, cacheable,uniform interface的protocol,所以实际上REST被默认就是用HTTP来实现,很多人耳熟能详HTTP的verb如何对应到resource的CRUD,仿佛也成了REST风格本身的死规定。我认为其实不然,以HTTP中的PUT为例,如果用PUT来实现resource的update,那么就必须要保证idempotent,每次传给server的信息,必须是resource的全部信息,不能作partial update。不难发现,用PUT来实现update,其实是在REST的constraint上又加上了HTTP的一些限制。如果我们放弃PUT的constraint,采用POST来实现update,则partial update是可以的。紧接着就由一个问题,既然PUT被POST替代,那么我们是否可以用POST来代替GET和DELETE呢?笔者认为应该没问题,一个很现实的例子,如果browser不支持DELETE,用POST来work around是很常见的。
okay, 再来看看SOAP,很多在HTTP上实现的SOAP协议就是用POST来实现的 (wikipedia里SOAP的一个sample http://en.wikipedia.org/wiki/SOAP#Example_message)
因此,当我们使用HTTP POST来实现REST,再加上XML的数据传输格式,其实我们就是在SOAP上面实现了RESTFul的"风格"(尽管还网上没人提到RESTful SOAP,但我觉得这在理论上是没问题的)。
与RESTful SOAP相对的一个例子,很多基于Rails的website(并非说Rails不好,Rails大行其道使得REST风行,故举例)URL风格是/callSomeMethodWithArgumentA, /callSomeMethodWithArgumentB,非常长,不uniform,不满足REST的限制,这些route都是不RESTFul的,我们可以称之为non-RESTful HTTP
长话短说,本人认为SOAP协议和REST架构风格是兼容的。虽然,约定俗成,REST的具体实现一般采用HTTP,且充分利用HTTP verb的不同特性,从而形成了一些约定俗称的范式,但这种实现本身不是REST"风格"的核心。
目前,大部分Web开发者似乎都了解REST——一种采用标准URI进行调用的方案。REST很容易理解,而且只要是支持HTTP/HTTPS的客户端/服务器就支持它。你可以用HTTP GET方法来执行命令。所以,开发者们感受到的REST的优势是:开发简单、只需依托现有Web基础设施、以及学习成本低。
然而,SOAP作为一种古老的Web服务技术,短期内还不会退出历史舞台。而且,随着SOAP 1.2的出现,SOAP印象中的一些缺点已得到改进,采纳率和易用程度也都得到提高。另需注意的是,从W3C SOAP 1.2版开始,SOAP这一缩写不再代表Simple Object Access Protocol(简单对象访问协议),而是仅仅作为协议名称而已。
相对REST而言,SOAP 1.2多出一些开销,不过这些开销也带来了一些好处。首先,SOAP在三个方面离不开XML(Extensible Markup Language,可扩展标记语言):SOAP信封(envelope)是基于XML的,它定义了消息里有什么以及如何处理它;一套用于数据类型的编码规则;过程调用和响应的规划。SOAP信封由传输协议(HTTP/HTTPS)发出,RPC(Remote Procedure Call,远程过程调用)得到执行,然后一个XML文档随SOAP信封返回。
需要注意的是,基于“通用”传输协议是SOAP的一个优点。REST目前基于HTTP/HTTPS;而SOAP可支持任何传输协议,从HTTP/HTTPS到SMTP(Simple Mail Transfer Protocol,简单邮件传送协议),甚至JMS(Java Messaging Service,Java消息传递服务)。不过,由于XML较为冗长且解析费时,因此采用XML也成为一个弊端。
不过,对Web开发者来说的好消息是,目前上述两种方案都是行之有效的方案。REST和SOAP都能解决许多Web方面的问题与挑战,而且在许多情况下,它们各自都能满足开发者的要求,也就是说可互换使用。
但很多人不知道,这两种技术可以混合搭配使用。REST很好理解,且极易上手;不过由于它缺乏标准,因此只被看作是一种架构方法。与之相比,SOAP是一个工业标准,它具备良好定义的协议,以及一套良好确立的规则,在大型和小型系统中均有采用。
因此,REST的适用场合包括:
有限的带宽和资源 别忘了返回的结构可以采用(由开发者定义的)任何格式。另外,由于REST采用标准的GET、PUT、POST和DELETE动词,因此可被任何浏览器所支持。除此以外,REST还可以使用为目前大多数浏览器支持的XMLHttpRequest对象,这为AJAX增色不少。
完全无状态的操作 对于那些需多步执行的操作,REST并非最佳选择,采用SOAP更合适。但是,如果你需要无状态的CRUD(Create/Read/Update/Delete,创建/读取/更新/删除)操作,那么应采用REST。
缓存考虑 若要利用无状态操作的特性,使得信息可被缓存,那么REST是很好的选择。
以上已经覆盖很多方案了,那么,为什么还要考虑SOAP呢?正如前述,SOAP比较成熟而且是经过良好定义的,具有完整的规范。而REST只不过是一种方法,对开发未作任何规约;因此,假如你遇到以下场合,那么SOAP是最佳选择:
异步处理与调用 如果你的应用需要确保可靠性与安全性,那么请采用SOAP。SOAP 1.2为确保这种操作补充定义了WSRM(WS-Reliable Messaging)等标准。
形式化契约 若提供者/消费者双方必须就交换格式取得一致,那么采用SOAP更合适。SOAP 1.2为这种交互提供了严格的规范。
有状态的操作 如果应用需要上下文信息与对话状态管理,那么应采用SOAP。SOAP 1.2为此补充定义了WS-Security、WS-Transactions和WS-Coordination等标准。相比之下,REST方法要求开发者自己来实现这些框架性工作。
正如你所看到的,REST和SOAP各自有其用武之地。它们在安全性和传输层等方面有着自己的潜在问题,不过它们都能完成任务,而且在许多情况下,它们都丰富了Web的技术手段。因此,就这一论题,其实最好的原则就是灵活性原则;因为至少在现今的Web开发中,无论面对何种问题,Web开发者们总有办法运用好这两种技术中的一种。