REST 简介

REST 是一个术语的缩写,REpresentational State Transfer,中文直译「表征状态转移」,这是个很拗口的词。我的建议是先不要强行理解,直接看怎么做,等对实施细节有一些了解后,再来看名字会有更深刻的理解。REST 是一套风格约定,RESTful 是它的形容词形式;比如一套实现了 REST 风格的接口,可以称之为 RESTful 接口。

REST 对请求的约定

REST 用来规范应用如何在 HTTP 层与 API 提供方进行数据交互;在现阶段,你应该已经很熟悉 GET 和 POST 请求;甚至有可能因为受限于后端框架限制等原因,你的整个应用全都是用这两种 HTTP 方法来完成的。这样无疑浪费了 HTTP 协议的潜力,而 REST 则充分利用了 HTTP 规范中的方法,达到接口描述的语义化。

REST 描述了 HTTP 层里客户端和服务器端的数据交互规则;客户端通过向服务器端发送 HTTP(s)请求,接收服务器的响应,完成一次 HTTP 交互。这个交互过程中,REST 架构约定两个重要方面就是 HTTP 请求的所采用方法,以及请求的链接。

在请求层面,REST 规范可以简单粗暴抽象成以下两个规则:

1. 请求 API 的 URL 表示用来定位资源;

2. 请求的 METHOD 表示对这个资源进行的操作;

以下将以这两个规则为基础,描述如何构造一个符合 REST 规范的请求。

一、API 的 URL

URL 用来定位资源,跟要进行的操作区分开,这就意味这 URL 不该有任何动词;

下面示例中的 get、create、search 等动词,都不应该出现在 REST 架构的后端接口路径中。在以前,这些接口中的动名词通常对应后台的某个函数。比如:

/api/getUser
/api/createApp
/api/searchResult
/api/deleteAllUsers

当我们需要对单个用户进行操作时,根据操作的方式不同可能需要下面的这些接口:

/api/getUser (用来获取某个用户的信息,还需要以参数方式传入用户 id 信息)
/api/updateUser (用来更新用户信息)
/api/deleteUser (用来删除单个用户)
/api/resetUser (重置用户的信息)

更有甚者,可能在更新用户不同信息时,提供不同的接口,比如:

/api/updateUserName
/api/updateUserEmail
/api/updateUser

这样的弊端在于:首先加上了动词,肯定是使 URL 更长了;其次对一个资源实体进行不同的操作就是一个不同的 URL,造成 URL 过多难以管理。

其实当你回过头看「URL」 这个术语的定义时,更能理解这一点。URL 的意思是统一资源定位符,这个术语已经清晰的表明,一个 URL 应该用来定位资源,而不应该掺入对操作行为的描述。

在 REST 架构的链接应该是这个样子:

  1. URL 中不应该出现任何表示操作的动词,链接只用于对应资源;
  2. URL 中应该单复数区分,推荐的实践是永远只用复数;比如 GET /api/users 表示获取用户的列表;如果获取单个资源,传入 ID,比如 /api/users/123 表示获取单个用户的信息;
  3. 按照资源的逻辑层级,对 URL 进行嵌套,比如一个用户属于某个团队,而这个团队也是众多团队之一;那么获取这个用户的接口可能是这样:
GET /api/teams/123/members/234 表示获取 id 为 123 的小组下,id 为234 的成员信息

按照类似的规则,可以写出如下的接口

/api/teams (对应团队列表)
/api/teams/123 (对应 ID 为 123 的团队)
/api/teams/123/members (对应 ID 为 123 的团队下的成员列表)
/api/teams/123/members/456 (对应 ID 为 123 的团队下 ID 未 456 的成员)

二、API 请求的方法

在很多系统中,几乎只用 GET 和 POST 方法来完成了所有的接口操作;这个行为类似于全用 DIV 来布局。实际上,我们不只有GET 和 POST 可用,在 REST 架构中,有以下几个重要的请求方法:GET,POST,PUT,PATCH,DELETE。这几个方法都可以与对数据的 CRUD 操作对应起来。

【Read】,资源的读取,用 GET 请求;比如:

GET /api/users  ( 表示读取用户列表)

GET 应当实现为一个安全方法。用于获取数据而不应该产生副作用。

【Created】,资源的创建,用 POST 方法;

POST 是一个非幂等的方法,多次调用会造成不同效果;

幂等(Idempotent):如果对服务器资源的多次请求与一次请求造成的副作用是一样的的话,那这个请求方法可以被认为是幂等。

比如下面的请求会在服务器上创建一个 name 属性为 'John Snow' 的用户;多次请求就会创建多个这样的用户。

POST /api/users
{
"name": "John Snow"
}

【Update】,资源的更新。用于更新的 HTTP 方法有两个,PUT 和 PATCH。

他们都应当被实现为幂等方法,即多次同样的更新请求应当对服务器产生同样的副作用。

PUT 和 PATCH 有各自不同的使用场景:

PUT 用于更新资源的全部信息,在请求的 body 中需要传入修改后的全部资源主体;

而 PATCH 用于局部更新,在 body 中只需要传入需要改动的资源字段。

设想服务器中有以下用户资源 /api/users/123

{
"id": 123,
"name": "Original",
"age": 20
}

当我们往后台发送更新请求时,PATCH 和 PUT 造成的效果是不一样。

PUT /api/users/123
{
"name": "PUT Update"
}

上述 PUT 请求操作后的内容是:

{
"id": 123,
"name": "PUT Update"
}

可以观察到,资源原有的 age 字段被清除掉了。

而如果改用 PATCH 的话,

PATCH /api/users/123
{
"name": "PATCH Update"
}

更新后的内容是:

{
"id": 123,
"name": "PATCH Update",
"age": 20
}

请求中指定的 name 属性被更新了,而原有的 age 属性则保持不变。

PATCH 的作用在于如果一个资源有很多字段,在进行局部更新时,只需要传入需要修改的字段即可。否则在用 PUT 的情况下,你不得不将整个资源模型全都发送回服务器,造成网络资源的极大浪费。

【Delete】,资源的删除,相应的请求 HTTP 方法就是 DELETE。这个也应当被实现为一个幂等的方法。如:

DELETE /api/users/123

用于删除服务器上 ID 为 123 的资源,多次请求产生副作用都是,是服务器上 ID 为 123 的资源不存在。

三、分页、过滤

REST 风格的接口地址,表示的可能是单个资源,也可能是资源的集合;当我们需要访问资源集合时,设计良好的接口应当接受参数,允许只返回满足某些特定条件的资源列表。

比如支持以 offset 和 limit 参数来进行分页;

GET /api/users?offset=0&limit=20

支持提供关键词进行搜索,以及排序

GET /api/users?keyword=john&sort=age

支持根据字段进行过滤

GET /api/users?gender=male

设计合适的 API URL,以及选择合适的请求方法,可以语义化的描述一个 HTTP 请求的操作。

当我们都熟悉且遵循这样的规范后,基本可以看到一个 REST 风格的接口就知道如何使用这个接口进行 CRUD 操作了。比如下面这面这个接口就表示搜索 ID 为 123 的图书馆的书,并且书的信息里包含关键字「game」,返回前十条满足条件的结果。

GET /api/libraries/123/books?keyword=game&sort=price&limit=10&offset=0

同样,下面这个请求的意思也就很明显了吧。

PATCH /api/companies/123/employees/234
{
"salary": 2300
}

总结

限于篇幅限制,本文仅从请求的角度选取了几个重点描述了实现 RESTful 接口需要满足的基本要求。关于 REST 的更多详细规范,可以参考这个仓库

转自:RESTful 接口实现简明指南

RESTful 接口实现简明指南的更多相关文章

  1. Java8简明指南

    Java8简明指南 转载自并发编程网 – ifeve.com本文链接地址: Java8简明指南 欢迎来到Java8简明指南.本教程将一步一步指导你通过所有新语言特性.由短而简单的代码示例,带你了解如何 ...

  2. RESTful 接口调试分享利器 restc

    这个工具来自于https://elemefe.github.io/restc/  这里对Abp进行了一次封装 1.在项目中添加nuget包 Abp.Web.Api.Restc 2.在项目Abp模块的D ...

  3. RESTful接口设计原则/最佳实践(学习笔记)

    RESTful接口设计原则/最佳实践(学习笔记) 原文地址:http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api 1 ...

  4. Swagger+Spring mvc生成Restful接口文档

    简介 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模型紧密集 ...

  5. [转]简单识别 RESTful 接口

         本文描述了识别一个接口是否真的是 RESTful 接口的基本方法.符合 REST 架构风格的接口,称为 RESTful 接口.本文不打算从架构风格的推导方面描述,而是从 HTTP 标准的方面 ...

  6. 【转】git - 简明指南

    git - 简明指南 助你入门 git 的简明指南,木有高深内容 ;) 作者:罗杰·杜德勒 感谢:@tfnico, @fhd 和 Namics其他语言 english, deutsch, españo ...

  7. 底层restful接口修改分析

    记录接口调用次数,接口调用时间需求. 需要修改公共的类,就是restful接口,可以认为是底层的代码,具体的实现有哪些?插入数据库肯定不能影响性能.

  8. 组件接口(API)设计指南-文件夹

    组件接口(API)设计指南-文件夹 组件接口(API)设计指南[1]-要考虑的问题 组件接口(API)设计指南[2]-类接口(class interface) 组件接口(API)设计指南[3]-托付( ...

  9. RESTful接口设计原则和优点

    RESTful架构优点: 前后端分离,减少流量 安全问题集中在接口上,由于接受json格式,防止了注入型等安全问题 前端无关化,后端只负责数据处理,前端表现方式可以是任何前端语言(android,io ...

随机推荐

  1. js把字符串格式的时间转换成几秒前、几分钟前、几小时前、几天前等格式

    最近在做项目的时候,需要把后台返回的时间转换成几秒前.几分钟前.几小时前.几天前等的格式:后台返回的时间格式为:2015-07-30 09:36:10,需要根据当前的时间与返回的时间进行对比,最后显示 ...

  2. [Java] 各种常用函数

    1.writeInt()和readInt() 这两个函数并不是写入一个整数,读取一个整数.它们实际上是写入4个字节,读取4个字节. writeInt(int i)把i按四个字节,二进制形式写到输出流里 ...

  3. ASP.NET页面之间传值QueryString(1)

    QueryString是一种非常简单的传值方式,他可以将传送的值显示在浏览器的地址栏中.如果是传递一个或多个安全性要求不高或是结构简单的数值时,可以使用这个方法.但是对于传递数组或对象的话,就不能用这 ...

  4. Str 函数

    Str 函数 Visual Studio 2005 返回数字的 String 表示形式.     Public Shared Function Str(ByVal Number As Object) ...

  5. UDP收/发广播包原理及步骤

    原文链接地址:http://www.2cto.com/net/201311/254834.html UDP收/发广播包原理及步骤 如果网络中两个主机上的应用程序要相互通信,其一要知道彼此的IP,其二要 ...

  6. 使用def文件简化dll导出

    原文链接地址:http://www.cnblogs.com/TianFang/archive/2013/05/04/3059073.html 在C++中,我们可以通过 __declspec(dllex ...

  7. 停课day2

    感觉今天好颓啊,我才把昨晚那五道题a了,(但我明明一直在学啊,为啥这么慢,难道是我太笨了?) 闲话少叙,先说做法 问题 A: C Looooops 题目描述 对于C的for(i=A ; i!=B ;i ...

  8. 【BZOJ 1592】[Usaco2008 Feb]Making the Grade 路面修整 dp优化之转移变状态

    我们感性可证离散(不离散没法做),于是我们就有了状态转移的思路(我们只考虑单不减另一个同理),f[i][j]到了第i块高度为j的最小话费,于是我们就可以发现f[i][j]=Min(f[i-1][k]) ...

  9. Ubuntu下安装LNMP之nginx的安装

    Nginx 最初是作为一个 Web 服务器创建的,用于解决 C10k 的问题.作为一个 Web 服务器,它可以以惊人的速度为您的数据服务.但 Nginx 不仅仅是一个 Web 服务器,你还可以将其用作 ...

  10. 杭电hdu 2089 数位dp

    杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍 ...