本文出自 “子 孑 ” 博客。出处http://zhangjunhd.blog.51cto.com/113473/47283
1 .什么是 REST?
REST 是由 Roy Fielding 在他的论文 《 Architectural Styles and the Design of Network-based Software Architectures》 中提出的一个术语。
REST 是英文 Representational State Transfer 的缩写,有中文翻译为 “ 具象状态传输 ” (参考: 《 SIP/IMS网络中的 Representational State Transfer (REST)和数据分布》 )。
可以将 REST 归纳如下:
1.1 首先 REST 只是一种风格,不是一种标准
You will not see the W3C putting out a REST specification. You will not see IBM or Microsoft or Sun selling a REST developer's toolkit. Why? Because REST is just an architectural style. You can't bottle up that style. You can only understand it, and design your Web services in that style.
- Roger L. Costello 《 Building Web Services the REST Way 》 。
|
1.2 REST 是以资源为中心的
在 REST 中,认为 Web 是由一系列的抽象资源( Abstract Resource )组成,这些抽象的资源具有不同的具体表现形式 ((Representational State) 。譬如,定义一个资源为 photo ,含义是照片,它的表现形式可以是一个图片,也可以是一个 .xml 的文件,其中包含一些描述该照片的元素。或是一个 html 文件。并且这些具体的表现可以分布在不同的物理位置上。
1.3 REST 的目的是决定如何使一个定义良好的 Web 程序向前推进
一个程序可以通过选择一个 Web 页面上的超链 ( 这些链接代表资源 ) ,使得另一个 Web 页面 (Representational State of an abstract resource) 返回 (transfer) 到用户,使程序进一步运行。
1.4 REST 充分利用或者说极端依赖 HTTP 协议
它通过逻辑 URI 定位资源
在 REST 的定义中,一个 Web 应用总是使用固定的 URI 向外部世界呈现(或者说暴露)一个资源。
这里必须注意
1 ,一个 URI 对应一个资源。
2 ,这里的 URI 是一个逻辑 URI ,
一个逻辑 URI : [url]http://www.example.com/photo/logo[/url]
一个物理 URI : [url]http://www.example.com/photo/logo.html[/url]
通过分辨 HTTP Request Header 信息来分辨客户端是想要取得资源的哪一种表现形式的数据。
我们来看一个实际例子:
[url]http://www.example.com/photo/logo[/url] 指向 example.com 网站(可以视为一个 Web 应用)中类型为 photo ,名字为 logo 的资源。我们用浏览器访问这个 URI ,看到的将可能是一个 html 文档,其中用 <img src=”……” /> 来显示实际的照片。
[url]http://www.example.com/photo/logo[/url] 这个地址很可能会在服务器内部处理为 [url]http://www.example.com/photo.jsp?name=logo[/url] 这样的地址。 photo.jsp 是服务器端的一个动态脚本文件,根据 name 参数生成 html 文档返回给浏览器。
现在假设我们要获取这张照片的 XML 文档。 XML 文档中包含照片的文件名、文件大小、拍摄日期等等信息。也就是说我们要获取 “ 同一个资源的不同表现形式的数据 ” 。对于这个要求,我们可以很容易的用另一个 URL 地址达到: [url]http://www.example.com/xml/logo[/url] 。
但是,这就违背了 “URI 唯一标识一个资源 ” 的定义。如果我们要获取同一个资源的多种表现形式,那么就要使用更多的 URL ,从而给一个资源指定了多个不同的 URI 。
而在 REST 中,不管是获取照片的 xhtml 文档还是 XML 文档,或者照片文件本身,都是用同一个 URI ,就是 [url]http://www.example.com/photo/logo[/url] 。
那这是怎么办到的呢?是通过分辨 HTTP Request Header 信息来分辨客户端是想要取得资源的哪一种表现形式的数据。
当我们用浏览器访问一个网址时,浏览器会构造一个 HTTP 请求。这个请求有一个头信息,其中包括了本次请求接受何种类型的数据。通常浏览器发送的 HTTP 请求头中, Accept 的值都是 */* ,也就说接受服务器返回的任何类型的数据。
只要我们指定一个特定的 Accept 参数,那么服务器就可以通过判断该参数来决定返回什么类型的数据。所以在一个采用 REST 架构的应用中,要获取同一个资源的不同表现形式的数据,只需要使用不同的 HTTP 请求头信息就行了。
如果考虑为 Web 应用增加 Web Services ,这种技术的价值就体现出来了。比如写了一个程序,现在只需要构造一个包含 Accept: text/xml 的 HTTP 请求头,然后将请求发送到 [url]http://www.example.com/photo/logo[/url] 就可以了。返回的结果就是一个 XML 文档,而不是别的资源形式的数据。
在 REST 架构中,用不同的 HTTP 请求方法来处理对资源的 CRUD (创建、读取、更新和删除)操作
我们在 Web 应用中处理来自客户端的请求时,通常只考虑 GET 和 POST 这两种 HTTP 请求方法。实际上, HTTP 还有 HEAD 、 PUT 、 DELETE 等请求方法。而在 REST 架构中,用不同的 HTTP 请求方法来处理对资源的 CRUD (创建、读取、更新和删除)操作:
Ø POST: 创建
Ø GET: 读取
Ø PUT: 更新
Ø DELETE: 删除
经过这样的一番扩展,我们对一个资源的 CRUD 操作就可以通过同一个 URI 完成了:
[url]http://www.example.com/photo/logo[/url] (读取)
仍然保持为 [GET] [url]http://www.example.com/photo/logo[/url]
仍然保持为 [GET] [url]http://www.example.com/photo/logo[/url]
[url]http://www.example.com/photo/logo/create[/url] (创建)
改为 [POST] [url]http://www.example.com/photo/logo[/url]
改为 [POST] [url]http://www.example.com/photo/logo[/url]
[url]http://www.example.com/photo/logo/update[/url] (更新)
改为 [PUT] [url]http://www.example.com/photo/logo[/url]
改为 [PUT] [url]http://www.example.com/photo/logo[/url]
[url]http://www.example.com/photo/logo/delete[/url] (删除)
改为 [DELETE] [url]http://www.example.com/photo/logo[/url]
改为 [DELETE] [url]http://www.example.com/photo/logo[/url]
从而进一步规范了资源标识的使用。
通过 REST 架构, Web 应用程序可以用一致的接口( URI )暴露资源给外部世界,并对资源提供语义一致的操作服务。这对于以资源为中心的 Web 应用来说非常重要。
2 . RESTful Web Services 特点
通过将 HTTP Accept 类型设置为 text/xml ,我们便可以将资源返回的“具象状态”表示为可跨平台识别的数据。这是应用于 Web Services 的基础。
RESTful Web Service 具有以下特点:
2.1 无状态的
每一个来自客户端的 request 必须包含所有必要的信息,即不能从服务器端获得任何保存的上下文信息。
REST 的 “ 客户机-无状态-服务器 ” 约束禁止在服务器上保存会话状态。符合这一约束进行设计
1 ,可以提高系统的可靠性和可伸缩性。它不需要昂贵的维护和支持费用,因为状态并不在服务器上维护。
2 ,可以进行资源缓存。 Web 的高速缓存既可以驻留在客户主机中,也可以驻留在中间网络高速缓存服务器主机中。
2.2 HTTP 头中可见的统一接口和资源地址
通过对于 HTTP Head 的解析,我们便可以了解到当前所请求的资源和请求的方式。相对于 SOAP RPC 风格来说,我们必须解析 HTTP 体。
这样做对于一些代理服务器的设置,将带来很高的处理效率。
REST 系统中所有的动作和要访问的资源都可以从 H TTP 和 URI 中得到,这使得代理服务器、缓存服务器和网关很好地协调工作。而 RPC 模 型的 SOAP 要访问的资源仅从 URI 无法得知,要调用的方法也无法从 HTTP 中得知,它们都隐藏在 SOAP 消息中。
同样的,在 REST 系统中的代理服务器还可以通过 HTTP 的动作 (GET 、 POST) 来进行控制。

2.3 返回一般的 XML 格式内容
一般情况下,一个 RESTful Web Service 将比一个 SOAP RPC Web Service 占用更少的传输带宽。
POST/Order HTTP/1.1
Host:[url]www.northwindtraders.com[/url]
Content-Type:text/xml
Content-Length:nnnn
<UpdatePO>
<orderID>098</orderID>
<customerNumber>999</customerNumber>
<item>89</item>
<quantity>3000</quantity>
</UpdatePO>
|
POST/Order HTTP/1.1
Host:[url]www.northwindtraders.com[/url]
Content-Type:text/xml
Content-Length:nnnn
SOAPAction:”urn:northwindtraders.com:PO#UpdatePO”
<SOAP-ENV:Envelope
xmlns:xsi=”[url]http://www.3w.org/1999/XMLSchema/instance[/url]”
xmlns:SOAP-ENV=”[url]http://schemas.xmlsoap.org/soap/envelope[/url]”
xsi:schemaLocation=”[url]http://www.northwindtraders.com/schema/NPOSchema.xsd[/url]”>
<SOAP-ENV:Body xsi:type=”NorthwindBody”>
<UpdatePO>
<orderID>098</orderID>
<customerNumber>999</customerNumber>
<item>89</item>
<quantity>3000</quantity>
</UpdatePO>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
|
2.4 安全机制
REST 使用了简单有效的安全模型。 REST 中很容易隐藏某个资源,只需不发布它的 U RI ;而在资源上也很容易使用一些安全策略,比如可以在每个 URI 针对 4 个通用接口设置权限;再者,以资源为中心的 Web 服务是防火墙友好的,因为 GET 的 意思就是 GET , P UT 的意思就是 PUT ,管理员可以通过堵塞非 GET 请求把资源设置为只读的,而现在的基于 RPC 模型的 SOAP 一律工作在 HTTP 的 POST 上。
使用 SOAP RPC 模型,要访问的对象名称藏在方法的参数中,因此需要创建新的安全模型。
2.5 无法用于事务型的服务
对于事务型的服务,一个简单的例子就是银行事务,在那里用户可以把钱从一个账户转移到另一个账户上。用户不想直接操作资源(钱、银行账户等等),他们只想告诉银行他们想要达到的目的,并且让银行根据他们的利益对资源进行处理。
所以从这一条,我们应该明白,选择基于 REST 或 SOAP RPC 风格的 Web 服务,我们应该首先考虑这个服务是针对资源的还是针对活动的。
- James Snell , 面向资源与面向活动的 Web 服务, 英文原文 。
3 . JAX-WS
是 Java Architecture for XML Web Services 的缩写 , 简单说就是一种用 Java 和 XML 开发 Web Services 应用程序的框架 , 目前版本是 2.0, 它是 JAX-RPC 1.1 的后续版本。
JAX-WS2.0 用 JAXB2 来处理 Java Object 与 XML 之间的映射。
JAX-WS 通过 javax.xml.ws.Provider 接口来构建 REST 风格的终端。
4 . WADL
Web Application Description Language (WADL) 是由 SUN 公司提出的,旨在提供一种 Web 应用的描述语言。 WADL 主要描述一个 Web 应用的
- 资源列表 - 站点所有的资源
- 资源之间的关系 - 说明资源之间的链接关系
- 所有应用于每个资源的特定方法 - 应用于每个资源的 HTTP 方法,指定的输入和输出以及它们支持的数据格式
- 资源表现的形式 - 支持的 MIME 类型和所用到的 XML schemas

下面是一个 WADL 示例,它描述了 Yahoo 新闻搜索的应用。
- Lines 2 开始一个应用描述,定义所使用的 namespaces 。
- Lines 3–6 定义 XML 语法,这个示例中是两个 W3C XML Schema 。
- Lines 7–11 描述了 Yahoo 新闻搜索 Web 资源以及它所支持的 HTTP 方法。
- Lines 12–26 描述了 ‘search’ GET 方法 。
- Lines 13–21 描述输入 。
- Lines 22–25 描述所有可能的输出。
5 .关于 WADL 的项目介绍
wadl2java
A tool that generates client side stubs from WADL files. May be used from the command line or as an Apache Ant plug-in, see the wadl2java documentation for full details.
wadl2java_yahoo
A sample project that uses the wadl2java tool to create stubs for the Yahoo News Search Service . Includes a simple main method that uses the generated stubs to query for the latest Java news.
6 .建议阅读的资料
[1]Roy Thomas Fielding , Architectural Styles and the Design of Network-based Software Architectures
[2] RESTwiki
[8]WADL 语言作者 Marc Hadley's Blog