:如何构建REST风格的WEB地图服务

REST英文全称为Representational State Transfer(表述性状态迁移),是2000年Roy Thomas Fielding博士在他的毕业论文中首次提出的概念,国内一帮精英已经把Fielding的论文翻成了中文,但是看完论文还是很难搞清REST到底是什么。Leonard Richardson与Sam Ruby的新书《RESTful Web Services》对REST作了简单而具体的诠释,提出了面向资源架构(The Resource-Oriented Architecture)的设计方法。根据对书中内容的理解,我这里作一简单的总结,不一定对,仅供参考。

1 什么是REST

REST是一组设计原则,或说是一种风格,不是架构,Fielding在他的论文中表示符合REST原则的web服务将在可见性、可靠性与可伸缩性等方面获益,而且符合万维网创建的初衷。

Google map(http://maps.google.com/)就是REST风格的web服务一例,当光标热点移动时,左下角随之变化的URI可以看出它是根据URI在提供相应的web服务。

REST是一组广义的设计原则,REST本身并没有与Web、HTTP或URI绑定,REST设计原则包括客户-服务器、无状态、缓存、统一接口、分层系统等。既然原则中要求无状态,又何来表述性状态呢?REST原则的无状态指服务器端不保存客户应用状态,连接→请求→响应→断开,客户的上一次请求与下一个请求没有关系(这其实是HTTP的特征)。服务器端响应客户请求返回资源的表述及相关链接(想像一下google返回的页面),该表述的本身就是客户的当前状态,客户按照表述中提供的链接选择下一个表述,迁移到下一个状态。这是我从字面上对REST的解释,也就是服务器通过表述为状态迁移提供指导,而状态的迁移权掌控在用户手里,客户根据自己的需要选择链接,由当前状态迁移到下一个状态。这个解释很肤浅,下面的面向资源架构从根本上对REST作了技术上的诠释。

2 面向资源架构

面向资源架构是一种REST风格的架构,它以资源为研究对象,通过划分资源、定义资源,然后用超媒体将资源串起来,提供客户所需求的服务。面向资源架构包括四个组成元素,具有四个属性。四个组成元素是:资源、资源名、资源表述和链接。四个属性是:可寻址、无状态、连通和统一接口。

2.1 四个元素

(1) 资源

就象面向对象设计取决于问题域对象划分一样,面向资源设计的首要任务就是划分资源,实际上面向资源是极端的面向对象,因为REST中规定了统一接口约束,要求对资源的操作必须是可见的(如HTTP中标准的GET、PUT、DELETE、POST,带暗箱操作的POST不算),因此资源的操作方法是不能自行定义的。

在面向资源设计中的资源可以是任何具有超文本链接价值的东西,资源可以是数据资源,也可以是物理对象,物理对象本身不能在网上传输,但物理对象的元数据可以。当统一接口方法不能满足需求时,可以通过设计资源将操作名词化,例如你“订阅”某个栏目,统一接口中没有“订阅”操作,也不允许你自行定义“订阅”操作,怎么办呢?你可以将“订阅”设计为资源“订阅关系”,“订阅关系”就可以用统一接口中的方法,如GET、PUT、DELETE进行操作了。同样,对于需要异步完成的操作,也可以通过资源将异步操作划分为多个同步操作来完成。总之,资源可以是任何东西,遇到困惑时可以设法通过资源来解决。

(2) 资源名

资源能成为资源的必要条件是:每个资源必须用URI唯一标识。这符合Tim Berners-Lee公理:Web上每一个资源由URL唯一确定。超文本系统、HTTP和Internet分层协议之间是不能交流的,URI把所有这些协议集成到了web中。资源用URI命名,资源通过URI定位,URI中不仅包含资源的地址,还包含对资源的操作指令,服务器端根据URI中的指令确定客户请求的处理方式。因此,这里的URI不是单纯的网址。

(3) 资源表述

资源是表述的数据源,表述是资源的当前状态(应客户请求返回的网页),对REST风格的服务来说表述是超媒体,表述中不仅包含着当前资源的信息,还包含了相关资源的链接。

因此,表述呈现了资源的当前状态,也链接着资源的其它状态。表述具体涉及资源的数据及数据格式。可用于表述的超媒体格式有多种,如: 应用/XHTML+XML、应用/ATOM+XML、图像/SVG+XML、应用/JSON、应用/WADL+XML。《RESTful Web Services》书中对WADL(Web Application Description Language,https://wadl.dev.java.net)较为推崇,WADL是用于描述HTTP资源特征的XML格式定义(词汇表),书中认为WADL剥离了HTTP请求和响应(表述的建造与解析)的细节,支持URI模板及HTTP统一接口,可以特定符合XML Schema定义的XML表述格式,可简化web服务的客户端编程,与其它超媒体格式相比,WADL有其独特的优点。

(4) 资源链接

资源不是孤立的,是可以连通的,资源通过Link或Form链接,Link与Form本身就是资源表述的一种,因此说表述是超媒体。

2.2 四个属性

(1) 可寻址

每个资源由唯一的URI标识,使资源可定位,也因此使缓存成为可能。

(2) 无状态

客户请求与服务响应通过HTTP通信,HTTP本身是无状态的,HTTP请求在完全封闭的过程中完成,请求中包含了服务器完成请求所必需的全部信息,请求与请求之间没有关联。这样,服务器端无需等待、无需追踪,它只需要关心客户发送请求时的应用状态就足够了。服务器端的服务之间也不需要分工协作,服务扩展只是将服务插入负载均衡器就行了,这样就增强了服务的伸缩性能。

REST中的无状态是指仅有一种状态,该状态不在服务器端而在客户端。其实,从资源角度来说,服务器端也有状态,那就是资源状态。服务器应客户请求返回资源的表述,资源通过HTTP由资源状态迁移到客户应用状态;客户向服务器上传资源表述(例如Amazon的S3服务),客户应用状态通过HTTP迁移到服务器变成了资源状态,这是不是应该是REST的真正含义?

(3) 连通

资源应该以某种方式连通,也就是资源是链接的,不需要用户在浏览器中键入URI执行跳转。Link或Form链接是资源连通的超媒体。

(4) 统一接口

面向资源架构利用了HTTP的统一接口,HTTP统一接口提供了四种基本操作方法GET、PUT、DELETE和POST,面向资源架构要求所有服务按HTTP标准方式使用GET、PUT、DELETE和POST,这样安全性好,没有副作用产生,其次响应结果具幂等性(数学上术语),即同一请求返回的结果总是相同的(如:任何数不管乘零多少次结果总是零),除非底层资源发生变化。

3 以一个Web地图服务为例

这是《RESTful Web Services》书中一个最简单的例子,因为Web地图是只读的服务。我只是简单总结,以便大家对REST风格的架构有一个直观的认识。

设计步骤如下:

l 分析数据集

l 将数据集划分为资源

对每一个资源

l 用URI给资源定名

l 选择统一接口方法

l 设计客户端→服务器的表述

l 设计服务器→客户端的表述

l 用超媒体链接或表单将资源挂接到现有资源链中

l 正面设想一下该发生什么

l 反面设想一下什么可能发生

 

(1) 分析数据集

本数据集为各大星球二维平面图,可以通过地理坐标及地名在地图上定位,并展示以点为中心的平面图。

(2) 将数据集划分为资源

资源大体分三类:

l 预定义的一次性资源,如同一个web主页,充当其它资源的顶级入口。你能GET它,但不能DELETE或PUT它。

l 每个对象的资源,每个对象有自己的资源集合,你可以GET、DELETE或PUT对象的资源。

l 经数据处理后获取的资源,例如根据查询条件返回的结果。

 

本web地图服务资源划分如下:

(1)所有星球列表

(2)某星球上某一个地方(包括整个星球),通过地名识别

(3)某星球上某地理位置,通过经纬度识别

(4)某星球上满足查询条件的地名列表

(5)以某点为中心的某星球地图

这些资源是可以连通的,星球列表中包含每个星球,每个星球包含无数个地方或地理位置,每个地方或地理位置对应以其为中心的地图。

 (3) 用URI给资源定名

在面向资源架构中,URI包含了客户请求的所有目标信息,有地址有操作指令。URI是具有语义的。

命名规则如下:

l 继承关系采用路径变量编码,如:/parent/child

l 无继承关系的,用标点符号区分,并列关系用分号,先后关系用逗号,如:/parent/child1;child2,或/parent/child1,child2

l 有处理请求的采用查询变量表示,如:/search?q=earch&start=20

 

本web地图服务资源命名如下:

资源

 

URI举例

 

(1)所有星球列表

 

http://maps.example.com/

 

(2)某星球上某一个地方(包括整个星球),通过地名识别

 

http://maps.example.com/Earth

http://maps.example.com/Earth/China/Qingdao

 

(3)某星球上某地理位置,通过经纬度识别

 

http://maps.example.com/Earth/36.08,120.35

 

(4)某星球上满足查询条件的地名列表

 

http://maps.example.com/Earth?show=craters+bigger+then+1km

http://maps.example.com/Earth/China/Qingdao?show=hotel

 

(5)以某点为中心的某星球地图

 

http://maps.example.com/satellite/Earth/36.08,120.35

http://maps.example.com/road/Earth/36.08,120.35

大比例尺图

http://maps.example.com/ road.10/Earth/36.08,120.35

小比例尺图

http://maps.example.com/ road.1/Earth/36.08,120.35

 

 

(4) 选择统一接口方法

HTTP提供了四种基本操作方法

l GET:取一个资源的表述

l PUT:创建一个新资源,或修改已有的资源

l DELETE:删除已有资源

l POST:创建已有资源的子资源

本web地图服务是只读的,只需要GET就够了。可以通过HTTP的Last-Modified和Etag,实施条件GET操作。

(5) 设计客户端→服务器的表述(以XHTML为例)

是客户需要填写的表单,如:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<form id="searchplace" method="get" action="">

<p>

Show place,feature,or business:

<input id="term" repeat="template" name="show"/>

<input class="submit"/>

</p>

</form>

</html>

(6) 设计服务器→客户端的表述(以XHTML为例)

l 所有星球列表

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>

<title>Planet List</title>

</head>

<body>

<ul class="planets">

<li><a herf="/Earth">Earth</a></li>

<li><a herf="/Earth">Venus</a></li>

<li><a herf="/Earth">Mars</a></li>

</ul>

</body>

</html>

 

表述呈现了资源的当前状态,也链接着资源的其它状态,但表述并非必须呈现资源的全部状态,可以显示资源的部分状态,同时提供链接,客户可以通过链接转向剩余部分的状态。Google Map在web地图服务中将地图分割成256*256pixels的图块,按客户请求一部分、一部分地显示资源的状态。这里的web地图服务也可以这样。

l 以点为中心的图

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>

<title>Road Mao of Earth</title>

</head>

<body>

<img class="map" src="/road.2/Earth/images/37.0,-95.8.png" alt="Map tile">

<a class="map_nav" herf="46.0518,-95.8">North</a>

<a class="map_nav" herf="41.3776,-89.7698">Northeast</a>

<a class="map_nav" herf="36.4642,-84.5187">East</a>

<a class="map_nav" herf="32.3513,-90.4459">Southeast</a>

<a class="zoom_out" herf="/road.1/Earth/37.0,-95.8">Zoom out</a>

<a class="zoom_in" herf="/road.3/Earth/37.0,-95.8">Zoom in</a>

</body>

</html>

(7) 用超媒体链接或表单将资源挂接到现有资源链中

星球--(Link)-→地球--(Form)-→地球上叫青岛的地方--(Link)-→青岛--(Form)-→青岛某酒店位置--(Link)-→丽晶大酒店

(8) 正面设想一下该发生什么

 

(9) 反面设想一下什么可能发生

如:

l 客户请求的图不存在,响应代码404(Not Found), 或响应代码200(OK)附以一个表述,表述中有相关链接,可能可以找到客户请求的图。

l 客户输入的地名不存在,响应代码404(Not Found),或响应代码303(See Other),附以一组相近的地名供选择

l 客户输入不合理的经纬度,如300,181,响应代码400(Bad Request)

l 服务器问题,返回503(Service Unavailable)或500(Internal Server Error)

4 结语

REST风格的面向资源架构基于三个基本的技术:HTTP,URI和XML,但注意它并没有与HTTP绑定,它只是利用了HTTP的统一接口。该架构以资源为中心,服务器端的状态是资源状态,客户端的状态是资源的表述状态,服务器端应客户请求返回资源的表述,资源通过HTTP由资源状态迁移为客户端的表述状态;客户向服务器端上传资源表述,资源由客户端的表述状态通过HTTP迁移为服务器端的资源状态。资源用URI唯一标识、用XML超媒体表述并链接,由HTTP统一接口执行资源操作。这样使得REST风格的面向资源web服务是可见的、可靠的、可伸缩的。

 

你可能感兴趣的:(REST)