RESTful初识
这阵子正打算用Rails做个东东,所以开始系统地学习起了Rails。巧合的是,大概两周前,dlee邀请我加入Fielding博士关于REST的那
篇论文的翻译团队。可以说Rails和REST这两个最热门的词汇几乎同时挤入了我的生活。随着我对Rails的学习和对[Fielding]的翻译,我
也开始对REST产生了一些不太成熟的想法,写在这里与大家分享,同时也起到抛砖引玉的作用,欢迎大家讨论。
先复习一下REST的基本思想。[Fielding]把REST形式化地定义为一种架构风格(architecture
style),它有架构元素(element)和架构约束(constraint)组成。这些概念比较晦涩难懂,而且我们做工程的往往并不需要形而上的理
解。我们只知道,REST是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。REST提出了一些设计概念和准则:
网络上的所有事物都被抽象为资源(resource);
每个资源对应一个唯一的资源标识(resource identifier);
通过通用的连接器接口(generic connector interface)对资源进行操作;
对资源的各种操作不会改变资源标识;
所有的操作都是无状态的(stateless)。
对于当今最常见的网络应用来说,resource identifier是url,generic connector
interface是HTTP,第4条准则就是我们常说的url不变性。这些概念中的resouce最容易使人产生误解。resouce所指的并不是数
据,而是数据+特定的表现形式(representation),这也是为什么REST的全名是Representational State
Transfer的原因。举个例子来说,“本月卖得最好的10本书”和“你最喜欢的10本书”在数据上可能有重叠(有一本书即卖得好,你又喜欢),甚至完
全相同。但是它们的representation不同,因此是不同的resource。
REST之所以能够简化开发,是因为其引入的架构约束,比如Rails
1.2中对REST的实现默认把controller中的方法限制在7个:index、show、new、edit、create、update和
destory,这实际上就是对CURD的实现。更进一步讲,Rails(也是当今大部分网络应用)使用HTTP作为generic connector
interface,HTTP则把对一个url的操作限制在了4个之内:GET、POST、PUT和DELETE。
REST之所以能够提高系统的可伸缩性,是因为它强制所有操作都是stateless的,这样就没有context的约束,如果要做分布式、做集
群,就不需要考虑context的问题了。同时,它令系统可以有效地使用pool。REST对性能的另一个提升来自其对client和server任务的
分配:server只负责提供resource以及操作resource的服务,而client要根据resource中的data和
representation自己做render。这就减少了服务器的开销。
既然REST有这样的好处,那我们应该义无反顾地拥抱它啊!目前一些大牛(像DHH)都已经开始投入到了REST的世界,那我们这些人应该做什么或者说思考写什么你呢?我觉得我们应该思考两个问题:
如何使用REST;
REST和MVC的关系。
第一个问题假设REST是我们应该采用的架构,然后讨论如何使用;第二个问题则要说明REST和当前最普遍应用的MVC是什么关系,互补还是取代?
我们先来谈谈第一个问题,如何使用REST。我感觉,REST除了给我们带来了一个崭新的架构以外,还有一个重要的贡献是在开发系统过程中的一种
新的思维方式:通过url来设计系统的结构。根据REST,每个url都代表一个resource,而整个系统就是由这些resource组成的。因此,
如果url是设计良好的,那么系统的结构就也应该是设计良好的。对于非高手级的开发人员来说,考虑一个系统如何架构总是一个很抽象的问题。敏捷开发所提倡
的Test Driven
Development,其好处之一(我觉得是最大的好处)就是可以通过testcase直观地设计系统的接口。比如在还没有创建一个class的时候就
编写一个testcase,虽然设置不能通过编译,但是testcase中的方法调用可以很好地从class使用者的角度反映出需要的接口,从而为
class的设计提供了直观的表现。这与在REST架构中通过url设计系统结构非常类似。虽然我们连一个功能都没有实现,但是我们可以先设计出我们认为
合理的url,这些url甚至不能连接到任何page或action,但是它们直观地告诉我们:系统对用户的访问接口就应该是这样。根据这些url,我们
可以很方便地设计系统的结构。
让我在这里重申一遍:REST允许我们通过url设计系统,就像Test Driven Development允许我们使用testcase设计class接口一样。
OK,既然url有这样的好处,那我们就着重讨论一下如何设计url。网络应用通常都是有hierarchy的,像棵大树。我们通常希望url也
能反映出资源的层次性。比如对于一个blog应用:/articles表示所有的文章,/articles/1表示id为1的文章,这都比较直观。遗憾的
是,网络应用的资源结构永远不会如此简单。因此人们常常会问这样一个问题:RESTful的url能覆盖所有的用户请求吗?比如,login如何
RESTful?search如何RESTful?
从REST的概念上来看,所有可以被抽象为资源的东东都可以使用RESTful的url。因此对于上面的两个问题,如果login和search
可以被抽象为资源,那么就可以使用RESTful的url。search比较简单,因为它会返回搜索结果,因此可以被抽象为资源,并且只实现index方
法就可以了(只需要显示搜索结果,没有create、destory之类的东西)。然而这里面也有一个问题:search的关键字如何传给
server?index方法显然应该使用HTTP
GET,这会把关键字加到url后面,当然不符合REST的风格。要解决这个问题,可以把每次search看作一个资源,因此要创建create和
index方法,create用来在用户点击“搜索”按钮是通过HTTP
POST把关键字传给server,然后index则用来显示搜索结果。这样一来,我们还可以记录用户的搜索历史。使用同样的方法,我们也可以对
login应用REST,即每次login动作是一个资源。
现在,我们来复杂一些的东东。如何用url表达“category为ruby的article”?一开始可能想到的是/category
/ruby/articles,这种想法很直观。但是我觉得里面的category是不需要的,我们可以直接把“/ruby”理解为“category是
ruby”,也就是说“ruby”出现的位置说明了它指的就是category。OK,/ruby/articles,单单从这个url上看,我们能获得
多少关于category的信息呢?显然category隐藏在了url后面,这样做到底好不好,应该是仁者见仁,智者见智了。对于如何表达
category这样的东西,我还没想出很好的方式,大家有什么好idea,可以一起讨论。
另外还有一种url形式,它对应到程序中的继承关系。比如product是一个父类,book和computer是其子类。那么所有产品的url
应该是/products,所有书籍的url应该是/books,所有电脑的url应该是/computers。这一想法就比较直观了,而且再次验证了
url可以帮助我们进行设计的论点。
让我再说明一下我的想法:如果每个用户需求都可以抽象为资源,那么就可以完全使用REST。
由此看来,使用REST的关键是如何抽象资源,抽象得越精确,对REST的应用就越好。因此,如何改变我们目前根深蒂固的基于action的思想是最重要的。
有了对第一个问题的讨论,第二个问题就容易讨论多了。REST会取代MVC吗?还是彼此是互补关系(就像AOP对于OOP)?答案是It
depends!如果我们可以把所有的用户需求都可以抽象为资源,那么MVC就可以推出历史的舞台了。如果情况相反,那么我们就需要混合使用REST和
MVC。
当然,这是非常理想的论断。可能我们无法找到一种方法可以把所有的用户需求都抽象为资源,因为保证这种抽象的完整性(即真的是所有需求都可以)需
要形式化的证明。而且即使被证明出来了,由于开发人员的能力和喜好不同,MVC肯定也会成为不少人的首选。但是对于希望拥抱REST的人来说,这些都没有
关系。只要你开发的系统所设计的问题域可以被合理地抽象为资源,那么REST就会成为你的开发利器。
所以,所有希望拥抱REST的朋友们,赶快训练自己如何带上资源的眼镜看世界吧,这才是REST的核心所在。
转载自javaeye论坛 作者:AllenYoung
分享到:
相关推荐
restful接口示例代码restful接口示例代码restful接口示例代码restful接口示例代码
C# 一个简单的 Restful 服务端和 Restful 客户端 Demo
restful restful所需要的jar包 ========================================= Restlet, a RESTful Web framework for Java ========================================= http://www.restlet.org -------------------...
Restful C# 服务端篇之实现RestFul Service开发(简单实用)
.NET作为客户端,如何调用WEBAPI RESTFUL的服务端 .NET如何开发RESTFUL服务端
Spring CXF Restful 实例
RESTFUL接口文档模板,样式好看的接口文档模板,docx格式
一个RESTful的文件下载方法
本资源类似于 Postman 的 IDEA 插件Restful Fast Request,在IDEA安装该插件后,找到插件安装目录,【C:\\Users\\Administrator\\AppData\\Roaming\\JetBrains\\IntelliJIdea2021.3\\plugins\\Restful Fast Request ...
使用Spring 实现RESTful Web 服务 demo
Python Flask高级编程之RESTFul API前后端分离精讲第六章节Python Flask高级编程之RESTFul API前后端分离精讲第六章节Python Flask高级编程之RESTFul API前后端分离精讲第六章节Python Flask高级编程之RESTFul API...
开发restful接口应该遵循统一的规范,保持规范的统一才能方便维护和应用
restful2个例子
RESTful API设计规范.pdf
Java SpringBoot 课程 restful crud 实验资源 restful 风格的增删改查
restful api 接口说明. 总结 restful api 语法知识和常用的状态码含义.
该文档说明c#端如何创建和调用RestFul接口,并给出详细的代码说明,方便用户学习和深入掌握。
·包含RESTful Web services的真实案例,如Amazon的简单存储服务与Atom发布协议等 ·探讨各种流行编程语言的Web services客户端 ·展示如何用三种流行框架实现RESTful services —— Ruby on Rails、Restlet(基于...
thinkphp6 RESTful API开发 开发过程记录笔记 https://blog.csdn.net/weixin_41120504/article/details/115638094
通用restful返回工具类