老徐

Never underestimate your power to change yourself!

如何理解RESTful

| Comments

什么是REST

  REST的全称是:Representational State Transfer,直接翻译过来就是:表现层状态转移,表现层的意思就是资源, 这个词语读着比较难理解,网上有一种叫法比较容易理解,叫:URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。很简洁,就是看url就知道这个路由是什么了,然后看http的动词method就明白要做什么了,最后看他的 status code就知道返回结果了。REST最大的几个特点为:资源、统一接口、URI和无状态。

RESTful架构

  RESTful 是现在比较流行的一种设计风格,它提供了一组设计原则和约束条件,主要用于客户端与服务器的交互。RESTful架构更简洁,更有层次,更易于实现缓存等机制。
  记得刚工作那会,代码写的比较烂,比如说要写增加商品的路由,会写成下面这样,从RESTful角度来说,这样写其实已经违背了他统一接口和对URI的意义的原则

1
POST /create_product

  • 首先URI上最好不要有create,pudate,get等这种动词,URI上只要描述他是什么东西就行了,且以复数最好吧,比如说products,users,orders等等
  • 如果接口是增加,删除,更新等操作可以在请求方式上来表现,常见的有以下这些:
    GET    ->获取一个资源
    POST    ->添加一个资源
    PUT    ->修改一个资源
    DELETE    ->删除一个资源
    比如说要增加一个商品,可以写成这样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#TODO 增加商品
POST /products

#TODO 获取商品列表
GET /products

#TODO 获取某个单个商品
GET /products/1

#TODO 更新某个商品
PUT /products/1

#TODO 删除某个商品
DELETE /products/1


上面这样写明显很简洁,虽然有些URI是相同的,但并不会存在歧义,你只要看他的http method就知道是做什么操作的了,而且这样明显更有层次感,如果是嵌套路由的话,层次感就更明显了。
以上是一些人个见解,下面是网上摘来的一些比较专业的述语

RESTful详解

1.1 资源与URI

这里以github网站为例,给出一些还算不错的URI:

1
2
3
4
https://github.com/git
https://github.com/git/git/blob/master/block-sha1/sha1.h
https://github.com/git/git/pulls
https://github.com/git/git/pulls?state=closed

关于URI设计技巧:

  • 使用 _ 或 - 来让URI可读性更好,例如http://www.github.com/blog/translate-reward-plan%E3%80%82
  • 使用 / 来表示资源的层级关系,例如上面的/git/git/blob/master/block-sha1/sha1.h
  • 使用 ? 用来过滤资源,例如/git/pulls?state=closed用来表示git项目的所有推入请求中已经关闭的请求。
  • 使用,或;表示同级资源关系,例如/git/sha1/compare/ef7b53d18;bd638e8c1

1.2 统一资源接口

RESTful架构应该遵循统一接口原则,统一接口包含了一组受限的预定义的操作,所有资源的访问接口应该使用标准的HTTP方法如GET,PUT,POST,DELETE,并遵循这些方法的语义。

如果按照HTTP方法的语义来暴露资源,那么接口将会拥有安全性和幂等性的特性,例如GET和HEAD请求都是安全的, 无论请求多少次,都不会改变服务器状态。而GET、HEAD、PUT和DELETE请求都是幂等的,无论对资源操作多少次, 结果总是一样的,后面的请求并不会产生比第一次更多的影响。 下面列出了GET,DELETE,PUT和POST的典型用法:

GET

  安全且幂等 获取表示 变更时获取表示(缓存) 200(OK) - 表示已在响应中发出 204(无内容) - 资源有空表示 301(Moved Permanently) - 资源的URI已被更新 303(See Other) - 其他(如,负载均衡) 304(not modified)- 资源未更改(缓存) 400 (bad request)- 指代坏请求(如,参数错误) 404 (not found)- 资源不存在 406 (not acceptable)- 服务端不支持所需表示 500 (internal server error)- 通用错误响应 503 (Service Unavailable)- 服务端当前无法处理请求

POST

  不安全且不幂等 使用服务端管理的(自动产生)的实例号创建资源 创建子资源 部分更新资源 如果没有被修改,则不过更新资源(乐观锁) 200(OK)- 如果现有资源已被更改 201(created)- 如果新资源被创建 202(accepted)- 已接受处理请求但尚未完成(异步处理) 301(Moved Permanently)- 资源的URI被更新 303(See Other)- 其他(如,负载均衡) 400(bad request)- 指代坏请求 404 (not found)- 资源不存在 406 (not acceptable)- 服务端不支持所需表示 409 (conflict)- 通用冲突 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突) 415 (unsupported media type)- 接受到的表示不受支持 500 (internal server error)- 通用错误响应 503 (Service Unavailable)- 服务当前无法处理请求

PUT

  不安全但幂等 用客户端管理的实例号创建一个资源 通过替换的方式更新资源 如果未被修改,则更新资源(乐观锁) 200 (OK)- 如果已存在资源被更改 201 (created)- 如果新资源被创建 301(Moved Permanently)- 资源的URI已更改 303 (See Other)- 其他(如,负载均衡 ) 400 (bad request)- 指代坏请求 404 (not found)- 资源不存在 406 (not acceptable)- 服务端不支持所需表示 409 (conflict)- 通用冲突 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突) 415 (unsupported media type)- 接受到的表示不受支持 500 (internal server error)- 通用错误响应 503 (Service Unavailable)- 服务当前无法处理请求

DELETE

  不安全但幂等 删除资源 200 (OK)- 资源已被删除 301 (Moved Permanently)- 资源的URI已更改 303 (See Other)- 其他,如负载均衡 400 (bad request)- 指代坏请求 404 (not found)- 资源不存在 409 (conflict)- 通用冲突 500 (internal server error)- 通用错误响应 503 (Service Unavailable)- 服务端当前无法处理请求

  接下来再按一些实践中的常见问题 POST和PUT在创建资源的区别:所创建的资源的名称(URI)是否由客户端决定。 例如为为博客增加一个android的分类,生成的路径就是分类名/categories/android,那么就可以采用PUT方法。 客户端不一定都支持这些HTTP方法:较古老的基于浏览器的客户端,只能支持GET和POST两种方法。妥协的解决方法,通过隐藏参数_method=DELETE来传递真实的请求方法等措施来规避。 统一资源接口对URI的意义:统一资源接口要求使用标准的HTTP方法对资源进行操作,所以URI只应该来表示资源的名称,而不应该包括资源的操作,如下是一些不符合统一接口要求的URI:

1
2
3
4
5
GET /getUser/1
POST /createUser  
PUT /updateUser/1
DELETE /deleteUser/1
正确写法应该是 /User/1

不应该包含动词,具体的动作由请求方法来体现。

1.3 资源的表述

  资源的表述是指对资源在特定时刻的状态的描述,客户端通过HTTP方法可以获取资源,更准确说是资源的表述而已。 资源在外界的具体呈现,可以有多种表述形式,在客户端和服务端之间传送的也是资源的表述,而不是资源本身。 例如文本资源可以采用html、xml、json等格式,图片可以使用PNG或JPG展现出来。

  资源的表述包括数据和描述数据的元数据,例如,HTTP头”Content-Type” 就是这样一个元数据属性。通过HTTP内容协商,客户端可以通过Accept头请求一种特定格式的表述,服务端则通过Content-Type告诉客户端资源的表述形式。

1.4 资源的链接

  REST是使用标准的HTTP方法来操作资源的,但仅仅因此就理解成带CURD的Web数据库架构就太过于简单了。这种反模式忽略了一个核心概念:”超媒体即应用状态引擎”。 超媒体是什么?当你浏览Web网页时,从一个连接跳到一个页面,再从另一个连接跳到另外一个页面,就是利用了超媒体的概念:把一个个把资源链接起来.   要达到这个目的,就要求在表述格式里边加入链接来引导客户端。在《RESTful Web Services》一书中,作者把这种具有链接的特性成为连通性。下面我们具体来看一些例子。

1.5 状态的转移

  REST原则中的无状态通信原则,并不是说客户端应用不能有状态,而是指服务端不应该保存客户端状态。

Comments