当HTTP被发明出来的时候,其实REST就已经存在了。可惜这么多年来,WEB开发模式却越来越背离HTTP的本质,舍本逐末的追求起RPC之类的东西。此时REST重新回到人们的视线里,无疑让大家开始反思过去走过的弯路。
本文并不想从头介绍REST,只是想举例说明一下需要注意的问题:
先来看看人们对REST的困惑 :
REST长啥样?
最一般的REST例子,类似下面的样子:
POST /articles 创建
DELETE /articles/123 删除
PUT /articles/123 更新或创建
GET /articles/123 查看
顺便说说几个知识点:
GET操作是安全的。所谓安全是指不管进行多少次操作,资源的状态都不会改变。比如我用GET浏览文章,不管浏览多少次,那篇文章还在那,没有变化。当然,你可能说每浏览一次文章,文章的浏览数就加一,这不也改变了资源的状态么?这并不矛盾,因为这个改变不是GET操作引起的,而是用户自己设定的服务端逻辑造成的。
PUT,DELETE操作是幂等的。所谓幂等是指不管进行多少次操作,结果都一样。比如我用PUT修改一篇文章,然后在做同样的操作,每次操作后的结果并没有不同,DELETE也是一样。顺便说一句,因为GET操作是安全的,所以它自然也是幂等的。
POST操作既不是安全的,也不是幂等的,比如常见的POST重复加载问题:当我们多次发出同样的POST请求后,其结果是创建出了若干的资源。
安全和幂等的意义在于:当操作没有达到预期的目标时,我们可以不停的重试,而不会对资源产生副作用。从这个意义上说,POST操作往往是有害的,但很多时候我们还是不得不使用它。
还有一点需要注意的就是,创建操作可以使用POST,也可以使用PUT,区别在于POST是作用在一个集合资源之上的(/articles),而PUT操作是作用在一个具体资源之上的(/articles/123),再通俗点说,如果URL可以在客户端确定,那么就使用PUT,如果是在服务端确定,那么就使用POST,比如说很多资源使用数据库自增主键作为标识信息,而创建的资源的标识信息到底是什么只能由服务端提供,这个时候就必须使用POST。
浏览器不支持PUT/DELETE方法怎么办?
大部分浏览器只支持GET/POST方法,这使得我们无法完美的实现REST。对于这样的情况,大致有几种解决方法,一种是在表单里加入一个 _method之类名字的隐藏字段,用于表示真正的方法,另一种是使用X-HTTP-METHOD-OVERRIDE头信息来重载POST。
HTTP方法够用么?
从上面的例子,我们可以看到,通过使用已有的HTTP方法:POST,DELETE,PUT,GET就可以完成资源的增删改查,但在实际情况中,我们需要做的操作往往并不仅仅局限在简单的增删改查操作中,比如说我们要把一篇文章“置顶”,但是HTTP方法里没有一个和“置顶”操作相对应的方法,这时候该怎么办呢?REST对类似问题的解决方案是:创建一个新的资源!在上面的例子里,我们可以这样:
PUT /top_articles/123
通过创建出一个新的资源(top_articles),我们就可以使用简单的HTTP方法通吃一切操作了。
如何设计资源的URL?
最常见的资源命名方式是/controllers/id,不过这不是必须的,REST并没有强制规定URL必须符合哪种形式,你大可以按照自己的设想去自由的设计,实际编程时大致有两种方法:
一种是基于路径变量的命名,如:/china/beijing/laowang
基于路径变量的命名方式一般用来描述具有层次化的结构的资源。
另一种是基于查询变量的命名,如:/peopel?name=laowang
基于查询变量的命名方式一般用来描述某种算法的计算结果。
到底是使用基于路径的命名方式,还是基于查询的命名方式,取决于你看问题的角度和个人的喜好。
REST反对使用Session么?
REST拒绝Session!这是因为REST强调无状态性。这里的状态指的的应用状态,也可以称之为会话状态。一旦在服务端保持了这样的状态,那么架构的可扩展性将大打折扣。在REST看来,任何类似的状态本身都应该是一个独立的资源。
但也有人认为,现在可以很方便的把session存储在memcached之类的分布式缓存中,所以不是问题。
Cookie对REST有害么?
一分为二的看,如果Cookie里保存的是应用状态的话,就没有问题。因为应用状态本来就属于客户端。但如果使用Cookie保存类似PHPSESSIONID之类的东西就不对了,因为这样的数据并不属于客户端状态,它只不过是使用Session的借口而已。
再来看看REST在PHP中的现状 :
PHP里的REST实现案例不多,有点影响都就是CakePHP和Zend,下面分别看看他们的实现:
CakePHP:
设定路由:
Router::parseExtensions('xml');
Router::mapResources('articles');
编写控制器:
class ArticlesController extends AppController {
var $components = array('RequestHandler');
function view($id = null) {
$article = $this->Article->findById($id);
$this->set(compact('article'));
}
// ...
}
视图:
<articles>
<?php echo $xml->serialize($article); ?>
</articles>
差不多就这样了,相应的,还可以实现其他的功能,于是,如下REST操作便成为可能:
POST /articles
DELETE /articles/123.xml
PUT /articles/123.xml
GET /articles/123.xml
总体看,CakePHP的REST实现基本上是按Rails风格来实现的,大体还过得去。
参考链接:
http://book.cakephp.org/view/476/rest
http://c7y.phparch.com/c/entry/1/art,cakephp-rest
ZendFramework:
ZendFramework通过Zend_Rest组件来实现Rest功能:
服务端:
require_once 'Zend/Rest/Server.php';
function sayHello($who, $when)
{
return "Hello $who, Good $when";
}
$server = new Zend_Rest_Server();
$server->addFunction('sayHello');
$server->handle();
客户端:
require_once 'Zend/Rest/Client.php';
$client = new Zend_Rest_Client('http://path/to/server/script');
$client-> sayHello('Davey', 'Day');
echo $client->get();
这时候,我们看一下Web服务器的日志,会发现生成了一条如下的记录:
GET /path/to/servier/script?method=sayHello&arg0=Davey&arg1=Day&rest=1 HTTP/1.1
我们发现,实际操作方法是由URL中的method=sayHello指定的,而HTTP固有方法(GET/POST等)则成为了摆设,这是典型的RPC 风格,如果大家对比Zend_Rest和Zend_XmlRpc文档的话,会明显发现它们根本就是一个东西,所以说,Zend_Rest是一个REST伪实现。
参考链接:
http://framework.zend.com/manual/en/zend.rest.html
http://framework.zend.com/manual/en/zend.xmlrpc.html
=============================
此外,INFOQ上有几篇不错的文章:
http://www.infoq.com/cn/articles/rest-architecure
http://www.infoq.com/cn/articles/rest-introduction
http://www.infoq.com/cn/articles/rest-anti-patterns
http://www.infoq.com/cn/articles/webber-rest-workflow
分享到:
相关推荐
所有的材料上来就是一大堆的名词,SOAP, WSDL,看得头都要大了,后来提出来的REST就容易理解得多,虽然目前SOAP在企业级的web service中还有一席之地,但是在公共的Internet上,不是REST的服务实在不好意思和人打招呼...
通过URL来设计系统结构,抽象的是资源,而不是对象、过程,完成的是用户接口 REST API的开发框架介绍:JSR-311,REST Web Services框架 JAX-RS,java接口;### REST Web Application多层框架 REST 应用场景,适合和...
REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态 所有的数据,不过是通过网络获取的还是操作(增删改查)...
基于面向资源思想以及REST架构,首次提出了矿山资源抽象层的概念,将矿山中各个异构系统的功能、文档、界面、工作流等抽象为能够通过标准URI来唯一标识的抽象资源元数据,在决策或智能分析层通过对元数据的分析和处理来...
Presto资源管理Rest API 文档
Drest:一个将Doctrine实体暴露为REST资源节点的库
Django REST framework 中文文档,Django REST framework 中文翻译文档,Django REST framework 中文翻译
PHP通过VMware vCenter REST APIs 接口,获取所有虚机信息代码范例。 x-vmw-doc-deprecated-method: get x-vmw-doc-deprecated-path: /rest/vcenter/vm ...
基于nodejs的websocket平台,该平台包括异步的数据库调用,异步的rest api访问,以及能够提供rest api的服务。该平台能实现基于ws的聊天室,可以将聊天的信息调用rest api存储到数据库,可以通过网页访问该平台提供...
编译C++ REST SDK所需要的资源,在编译时,如果没有这些资源,会自动请求下载,但是速度非常慢。对应的编译文档地址为:https://blog.csdn.net/youyicc/article/details/105971772
2. 由于【1】的改动,使得只有以/rest开头的URL才能映射到某资源,使用rest服务时,必须要加上/rest。 3. 由于【1】的改动,RestComponent类注册application时将资源字符串加上了/rest。 4. 由于【1】的改动和本人...
REST入门知识及实例开发,涵盖REST设计原则,资源识别方法,在Jersey下开发RESTful webservice实现转账业务,包括服务端,客户端源码,详细阐述HTTP的4个请求方法(GET,POST,PUT,DELETE)在REST中的应用,使你...
ember-rest, 在 Ember.js 中,简单的rest式资源 注意:这个库不再支持,因为它对于大多数应用程序来说过于简单。 请考虑使用 Ember数据 。 @dgeb 2014-02-19 rest 一个在 Ember.js. 中实现rest化资源的简单的。简单...
关于restful风格的wcf资源文件,restwcf开发资源
REST实战(REST in Practice)。英文清晰PDF版。...你将会学习到很多技术,并且随着一家典型的公司从最初的小企业逐渐成长为全球化的企业,使用这些web技术和模式来解决这家公司在成长过程中产生的各种需求。
rest服务在Dlephi7里的调用方法,写了个demo,测试过,可以用的
包含翻译后的API文档:elasticsearch-rest-client-6.8.3-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.elasticsearch.client:elasticsearch-rest-client:6.8.3; 标签:elasticsearch、client、rest、中文...
Advanced REST client,Advanced REST client 依赖的json文件在其他的资源中。
Resoursea - 一个REST框架用于在Golang快速编写基于资源服务
包含翻译后的API文档:elasticsearch-rest-high-level-client-6.8.3-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.elasticsearch.client:elasticsearch-rest-high-level-client:6.8.3; 标签:elasticsearch...