如何给老婆解释什么是Restful【转载】

老婆常常喜欢翻看我订阅的技术杂志,她总能从她的视角提出不少有趣的问题。html

一个清闲的周日下午,她午觉醒来,又习惯性的抓起这个月的杂志,饶有兴趣地看了起来。程序员

果不其然,看着看着,她又对我发难了,“Restful是什么呀,老公?是restaurant的形容词吗,忽然就以为好饿了啊……”json

做为一个合格的程序员,我一直把可以将一项技术讲给老婆听,而且能给她讲懂,做为我已经掌握了这项技术的标准。 
若是我直接回答说,“REST就是Representational State Transfer的缩写呀,翻译为中文就是‘表述性状态转移’”,那她今晚确定得罚我跪键盘。我必须找个合适的机会,把Restful的前因后果给她形象的描述一遍。api

“走,我们去楼下咖啡厅吃个下午茶吧”,我对老婆说。bash

“一个芝士蛋糕,一杯拿铁,两条吸管,谢谢”,我对前台的服务员说,而后咱们找了个角落坐了下来。restful

Level 0 - 面向前台

“刚才咱们向前台点了一杯拿铁,这个过程能够用这段文字来描述”,说着,我在纸上写下了这段JSON,虽然她不知道什么叫JSON,但理解这段文字对于英语专业8级的她,实在再简单不过。架构

{
    "addOrder": { "orderName": "latte" } }
  • 1
  • 2
  • 3
  • 4
  • 5

“咱们经过这段文字,告诉前台,新增一笔订单,订单是一杯拿铁咖啡”,接着,前台给咱们返回这么一串回复:分布式

{
    "orderId": "123456" }
  • 1
  • 2
  • 3

“订单ID?仍是订单编号?” 
“恩恩,就是订单编号” 
“那咱们就等着前台喊‘订单123456的客户能够取餐了’,而后就能够开吃了!” 
“哈哈,你真聪明,不过,在这以前,假设咱们有一张会员卡,咱们想查询一下这张会员卡的余额,这时候,要向前台发起另外一个询问”,我继续在纸上写着:工具

{
    "queryBalance": { "cardId": "886333" } }
  • 1
  • 2
  • 3
  • 4
  • 5

“查询卡号为886333的卡的余额?” 
“真棒!接着,查询的结果返回来了”优化

{
    "balance": "0" }
  • 1
  • 2
  • 3

“切,没钱……” 
“哈哈,没钱,如今咱们要跟前台说,这杯咖啡不要了”,我在纸上写到:

{
    "deleteOrder": { "orderId": "123456" } }
  • 1
  • 2
  • 3
  • 4
  • 5

“哼,这就把订单取消啦?”

Level 1 - 面向资源

“如今这家咖啡店越作越大,来喝咖啡的人愈来愈多,单靠前台显然是不行的,店主决定进行分工,每一个资源都有专人负责,咱们能够直接面向资源操做。” 
“面向资源?” 
“是的,好比仍是下单,请求的内容不变,可是咱们多了一条消息”,我在纸上画出此次的模型:

/orders

{
    "addOrder": { "orderName": "latte" } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

“多了一个斜杠和orders?这是什么意思?” 
“这个表示咱们这个请求是发给哪一个资源的,订单是一种资源,咱们能够理解为是咖啡厅专门管理订单的人,他能够帮咱们处理全部有关订单的操做,包括新增订单、修改订单、取消订单等操做” 
“Soga…” 
“接着仍是会返回订单的编号给咱们”

{
    "orderId": "123456" }
  • 1
  • 2
  • 3

“下面,咱们仍是要查询会员卡余额,此次请求的资源变成了cards”

/cards

{
    "queryBalance": { "cardId": "886333" } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

“接下来是取消订单” 
“这个我会”,说着,她抢走我手上的笔,在纸上写了起来:

/orders

{
    "deleteOrder": { "orderId": "123456" } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Level2 - 打上标签

“接下来,店主还想继续优化他的咖啡厅的服务流程,他发现负责处理订单的员工,每次都要去订单内容里面看是新增订单仍是删除订单,仍是其余的什么操做,十分不方便,因而规定,全部新增资源的请求,都在请求上面写上大大的‘POST’,表示这是一笔新增资源的请求”

“其余种类的请求,好比查询类的,用‘GET’表示,删除类的,用‘DELETE’表示”

“还有修改类的,修改分为两种,第一种,若是这个修改,不管发送多少次,最后一次修改后的资源,老是和第一次修改后的同样,好比将拿铁改成猫屎,那么用‘PUT’表示;第二种,若是这个修改,每次修改都会让这个资源和前一次的不同,好比是加一杯咖啡,那么这种请求用‘PATCH’或者‘POST’表示”,一口气讲了这么多,发现她有点似懂非懂。

“来,咱们再来重复上面那个过程,来一杯拿铁”,我边说边画着:

POST /orders

{
    "orderName": "latte" }
  • 1
  • 2
  • 3
  • 4
  • 5

“请求的内容简洁多啦,不用告诉店员是addOrder,看到POST就知道是新增”,她听的很认真,理解的也很透彻。 
“恩恩,返回的内容仍是同样”

{
    "orderId": "123456" }
  • 1
  • 2
  • 3

“接着是查询会员卡余额,此次也简化了不少”

GET /cards { "cardId": "886333" }
  • 1
  • 2
  • 3
  • 4
  • 5

“这个请求咱们还能够进一步优化为这样”

GET /cards/886333
  • 1

“Soga,直接把要查询的卡号写在后面了” 
“没错,接着,取消订单”

DELETE /orders/123456
  • 1

Level 3 - 完美服务

“突然有一天,有个顾客抱怨说,他买了咖啡后,不知道要怎么取消订单,咖啡厅一个店员回了一句,你不会看咱们的宣传单吗,上面不写着:

DELETE /orders/{orderId}
  • 1

顾客反问道,谁会去看那个啊,店员不服,又说到,你瞎了啊你……听说后面两人吵着吵着还打了起来…” 
“噗,真是悲剧…”

“有了此次教训,店长决定,顾客下了单以后,不只给他们返回订单的编号,还给顾客返回全部能够对这个订单作的操做,好比告诉用户如何删除订单。如今,咱们仍是发出请求,请求内容和上一次同样”

POST /orders

{
    "orderName": "latte" }
  • 1
  • 2
  • 3
  • 4
  • 5

“可是此次返回时多了些内容”

{
    "orderId": "123456", "link": { "rel": "cancel", "url": "/order/123456" } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

“此次返回时多了一项link信息,里面包含了一个rel属性和url属性,rel是relationship的意思,这里的关系是cancel,url则告诉你如何执行这个cancel操做,接着你就能够这样子来取消订单啦”

DELETE /orders/123456
  • 1

“哈哈,这服务真是贴心,之后不再用担忧店员和顾客打起来了”

“订单123456的客户能够取餐了”,伴随着咖啡厅的广播,咱们吃起了下午茶,一杯拿铁,两支吸管……

对程序员的话

用了大白话,给老婆讲明白了RESTful的前因后果,固然,我仍是有些话想说的,只是怕老婆听完一脸懵逼,没给她说:

一、 
上面讲的Level0~Level3,来自Leonard Richardson提出的Richardson Maturity Model

这里写图片描述

Level0和Level1最大的区别,就是Level1拥有了Restful的第一个特征——面向资源,这对构建可伸缩、分布式的架构是相当重要的。同时,若是把Level0的数据格式换成Xml,那么其实就是SOAP,SOAP的特色是关注行为和处理,和面向资源的RESTful有很大的不一样。 
Level0和Level1,其实都很挫,他们都只是把HTTP当作一个传输的通道,没有把HTTP当作一种传输协议

Level2,真正将HTTP做为了一种传输协议,最直观的一点就是Level2使用了HTTP动词,GET/PUT/POST/DELETE/PATCH….,这些都是HTTP的规范,规范的做用天然是重大的,用户看到一个POST请求,就知道它不是幂等的,使用时要当心,看到PUT,就知道他是幂等的,调用多几回都不会形成问题,固然,这些的前提都是API的设计者和开发者也遵循这一套规范,确保本身提供的PUT接口是幂等的。

Level3,关于这一层,有一个古怪的名词,叫HATEOAS(Hypertext As The Engine Of Application State),中文翻译为“将超媒体格式做为应用状态的引擎”,核心思想就是每一个资源都有它的状态,不一样状态下,可对它进行的操做不同。理解了这一层,再来看看REST的全称,Representational State Transfer,中文翻译为“表述性状态转移”,是否是好理解多了?

Level3的Restful API,给使用者带来了很大的遍历,使用者只须要知道如何获取资源的入口以后的每一个URI均可以经过请求得到,没法得到就说明没法执行那个请求

如今绝大多数的RESTful接口都作到了Level2的层次,作到Level3的比较少。固然,这个模型并非一种规范,只是用来理解Restful的工具。因此,作到了Level2,也就是面向资源和使用Http动词,就已经很Restful了。Restful自己也不是一种规范,我比较倾向于用”风格“来形容它。若是你想深刻了解Level3,能够阅读《Rest in Practice》第五章。

二、 
我跟老婆讲的时候,用的数据格式是JSON,可是要强调一点,Restful对数据格式没有限制,就算你用的是XML或者其余格式,只要符合上面提到的几个特征,也算Restful。

三、 
关于如何写出好的Restful API,阮一峰老师已经写过一篇很是棒的文章:RESTful API 设计指南,这篇文章将指导你写出优雅的Restful。

相关文章
相关标签/搜索