RESTful API 实践

模式潮汐
• 阅读 5610

什么是 REST?

REST 即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格(http://www.ics.uci.edu/~field...)。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

六个约束:

  • 统一接口(Uniform Interface)

  • 无状态(Stateless)

  • 缓存(Cacheable)

  • 客户-服务器(Client-Server)

  • 分层系统(Layered System)

  • 按需代码(Code on Demand)

统一接口(Uniform Interface)

使REST 架构风格区别于其他基于网络的架构风格的核心特征是,它强调组件之间要有一个统一的接口。通过在组件接口上应用通用性的软件工程原则,整体的系统架构得到了简化,交互的可见性也得到了改善。实现与它们所提供的服务是解耦的,这促进了独立的可进化性。然而,付出的代价是,统一接口降低了效率,因为信息都使用标准化的形式来转移,而不能使用特定于应用的需求的形式。REST 接口被设计为可以高效地转移大粒度的超媒体数据,并针对Web的常见情况做了优化,但是这也导致了该接口对于其他形式的架构交互并不是最优的。

无状态(Stateless)

通信必须在本质上是无状态的,因此从客户到服务器的每个请求都必须包含理解该请求所必需的所有信息,不能利用任何存储在服务器上的上下文,会话状态因此要全部保存在客户端。

缓存(Cacheable)

为了改善网络的效率。缓存约束要求一个请求的响应中的数据被隐式地或显式地标记为可缓存的或不可缓存的。如果响应是可缓存的,那么客户端缓存就可以为以后的相同请求重用这个响应的数据。

客户-服务器(Client-Server)

通过分离用户接口和数据存储这两个关注点,我们改善了用户接口跨多个平台的可移植性;同时通过简化服务器组件,改善了系统的可伸缩性。然而,对于 Web来说,最重要的是这种关注点的分离允许组件独立地进化,从而支持多个组织领域的Internet规模的需求。

分层系统(Layered System)

分层系统风格通过限制组件的行为(即,每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。通过将组件对系统的知识限制在单一层内,为整个系统的复杂性设置了边界,并且提高了底层独立性。我们能够使用层来封装遗留的服务,使新的服务免受遗留客户端的影响,通过将不常用的功能转移到一个共享的中间组件中,从而简化组件的实现。中间组件还能够通过支持跨多个网络和处理器的负载均衡,来改善系统的可伸缩性。

按需代码(Code on Demand)

通过减少必须被预先实现的功能的数目,简化了客户端的开发。允许在部署之后下载功能代码也改善了系统的可扩展性。然而,这也降低了可见性,因此它只是 REST 的一个可选的约束。

HTTP 动作

GET

HTTP GET 用于检索(读取)资源。正确的情况返回JSON200 HTTP响应码,在错误的情况下他们通常返回404(NOT FOUND)400(BAD REQUEST)

示例

GET http://www.example.com/custom...
GET http://www.example.com/custom...
GET http://www.example.com/bucket...

通过GET它应该永远不会修改服务器上的任何资源。

POST

HTTP POST 通常用于创建资源。正确的情况返回201 HTTP响应码及Location header(资源 URI)。

示例

POST http://www.example.com/customers
POST http://www.example.com/custom...

PUT

HTTP PUT 通常用于更新资源。将请求正文内容替换已知资源的原始数据。

示例

PUT http://www.example.com/custom...
PUT http://www.example.com/custom...

DELETE

HTTP DELETE 用于删除由URI标识的资源。成功删除返回200 HTTP及响应正文或没有正文响应204 HTTP(NO CONTENT)

示例

DELETE http://www.example.com/custom...
DELETE http://www.example.com/custom...
DELETE http://www.example.com/bucket...

下表是 URI 结合 HTTP METHOD 建议的返回值

HTTP Verb(Method) /customers /customers/{id}
GET 200 (OK)。客户列表,数据量大可使用分页排序筛选 200 (OK)。单个客户。404 (Not Found) ID客户不存在,400 (BAD REQUEST) ID不合法
POST 201 (Created),'Location' header 为 /customers/{id} 包含新的资源ID 404 (Not Found)
PUT 404 (Not Found) 200 (OK)或者204 (No Content)。404 (Not Found) ID客户不存在,400 (BAD REQUEST) ID不合法
DELETE 404 (Not Found) 200 (OK)或者204 (No Content)。404 (Not Found) ID客户不存在,400 (BAD REQUEST) ID不合法

资源命名

一切在工艺软件开发的命名是成功的关键。

除了适当的应用 HTTP Verb(Method),资源命名可以说是最受争议和最重要的概念。当资源被命名好时,API 是直观和易于使用的。做得太差,同样的 API 能感觉太表面化和难以使用和理解。下面是一些提示,让你去当创建资源 URI 为您新的 API。

资源 URI 应使用名词而不是动词命名。一个 RESTful URI 应该指一种资源,而不是采取行动。名词具有属性而动词没有。

服务套件中每个资源至少有一个 URI 标识它。URI 应遵循一种可预见,分层结构,以增加可理解性,从而提高可用性。

在一个订单系统与客户、订单、行项目的资源设计:

创建一个新的客户
POST http://www.example.com/customers

读取客户 ID 为 33245
GET http://www.example.com/custom...
相同的 URI 将用于更新(PUT)与删除(DELETE)客户

这里为产品设计的 URI:
POST http://www.example.com/products
创建一个新的产品

GET|PUT|DELETE http://www.example.com/produc...
读取、更新、删除 ID 为 66432 的产品为

现在变得很有趣,我们如何为客户创建新的订单?
一种选择是
POST http://www.example.com/orders
毫无疑问它是可以工作的,但它却在客户的上下文之外

下面的 URI 更清晰
POST http://www.example.com/custom...
现在我们知道这个订单是为客户 33245 创建的

获取 33245 客户订单使用如下 URI
GET http://www.example.com/custom...
现在,我们继续来看分层的 URI 设计。如下:
POST http://www.example.com/custom...
这会将行项目添加到订单 #8769(这是客户 #33245),获取该 URI 资源会返回订单下所有的行项目,如果行项目毫无意义或者在客户的上下文以外的地方能感觉到我们会提供这样一个 URI
POST www.example.com/orders/8769/lineitems

看看一些广泛使用的 API 来得到资源命名窍门和利用你的队友来完善您的 API 资源。

Response Body

简单响应

示例

{
   "url":"https://api.github.com/gists/20c98223d9b59e1d48e5",
   "id":"1",
   "description":"description of gist",
   "public":true,
   "user":{
       "login":"octocat",
       "id":1,
       "avatar_url":"https://github.com/images/error/octocat_happy.gif",
       "gravatar_id":"somehexcode",
       "url":"https://api.github.com/users/octocat"
   },
   "comments":0,
   "comments_url":"https://api.github.com/gists/19d18b30e8af75090307/comments/",
   "html_url":"https://gist.github.com/1",
   "git_pull_url":"git://gist.github.com/1.git",
   "git_push_url":"git@gist.github.com:1.git",
   "created_at":"2010-04-14T02:15:15Z"
}

分页响应

  • total_count 总记录数

  • items 数据项

示例

{
   "total_count":40,
   "items":[
       {
           "id":3081286,
           "name":"Tetris",
           "full_name":"dtrupenn/Tetris",
           "owner":{
               "login":"dtrupenn",
               "id":872147,
               "type":"User"
           },
           "private":false,
           "html_url":"https://github.com/dtrupenn/Tetris",
           "description":"A C implementation of Tetris using Pennsim through LC4",
           "fork":false,
           "url":"https://api.github.com/repos/dtrupenn/Tetris",
           "created_at":"2012-01-01T00:31:50Z",
           "updated_at":"2013-01-05T17:58:47Z",
           "pushed_at":"2012-01-01T00:37:02Z"
       }
   ]
}

错误响应

  • code 错误码

  • message 错误信息

示例

{
   "code": 12345,
   "message": "错误描述"
}

参考资源

http://www.restapitutorial.com/
https://www.oschina.net/trans...

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
4年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
4年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这