1 概述

1.1 撰写目标

正文用于定义一种统一的RESTful接口设计方案,希望保有参考价值。本文所讲述的方案相比高校派,在上一家商家指出没有被拔取,在所精晓到的个其他多少家声称利用了RESTful风格的营业所里,发现他们也偏离甚远。当然,他们这么做是有理由的,我也精通,那只是挑选问题。那篇小说其实是旧文了,二〇一六年年末就早已写好,不过一直躺在微机的硬盘里,不想白费了当下的造诣,由此在此公开。

1.2 为啥采用REST

目标是为了服务端与客户端的解耦。SOA仅仅是从结构上校前后端分离,但是实际上数据逻辑依旧不曾兑现解耦,服务端接口升级往往会影响客户端,两者的行事必要从严约定。而REST采取HTTP协议举行预约,客户端仅仅须求依据HTTP协议来通晓服务端重临的数目,即便与事务有关的数据结构依旧需求预订,不过这实在越来越解耦了服务端与客户端。

除此以外,由于严峻听从HTTP协议举办多少重临,对于平安的接口,可以在再次来到的Header里设置缓存策略(接口安全性的概念在下文会解释)。

1.3 文档结构

其次片段将演说关于RESTful的若干个主要的定义,明确第二有些阐释的几个概念有利于统筹、完毕优雅规范的接口。

其三有些就URL命名的题目展开预约。

第四片段对音信实体举行预定。

第五局部对『向RESTful接口发起呼吁』举行解说,约定要完毕的艺术,约定请求的头顶和body的格式。

第六片段对接口的响应格式举办约定,包涵响应信息的头部、状态码、JSON实体。

第七片段对版本控制的题目展开预订。

第八片段对RESTful接口的落到实处指出了贯彻工具的提议。

2 关键概念

不言而喻一些最首要的概念是很紧要的,固然RESTful风格的API设计方案并没有统一的规范,不过仍旧须要符合自然的规则进行设计,否则就不可以称之为RESTful风格的API。因为许三人并没有对REST举行丰硕的刺探就宣称自己的API是RESTful风格的API,以至于RESTful的提议者Fielding大学生本人无法忍受,在二零零六年为此特意写了一篇博客『REST
APIs must be
hypertext-driven
』,hypertext-driven与HATEOAS是同一个定义的两样表明,在下文会进行演讲。

2.1 RESTful

REST不是一种协议,也不是一种文件格式,更不是一种开发框架。它是一多样的规划约束的集合:无状态性、将超媒体作为利用状态的发动机等。REST是Representation
State
Transfer
的缩写,中文是『表述性状态转移』,那里就涉及到资源的表述与气象六个概念。

简短地说,资源可以作为是服务器上囤积的具有数据,资源的发挥则是服务器对外提供的针对那些资源的主意,使用JSON、XML等均可,一个资源得以有多种表明;资源的状态则是服务器的数据存储状态,例如在t时刻,服务器中蕴藏了m条数据,那时候客户端向服务端提交了一个创立数量的呼吁,服务器处理了此呼吁并创立了一条数据,那么在t+1时刻,服务器中就存储了m+1条数据,那八个天天的资源气象就是不等同的,t时刻爆发的哀求导致了资源情形的转移。

2.2 HATEOAS

Hypermedia As The Engine Of Application
State
,超媒体作为应用程序状态的发动机。那是REST不一样于其余SOA风格的重点特征。客户端与服务端进行交互的时候,完全是由此服务端动态提供的超媒体进行的。除了对超媒体的相似领悟,客户端不需求领会其余附加的学问。相反,在有些SOA接口的宏图中,客户端与服务端的通信是要事先举办约定的,例如通过文档或者接口描述语言(Interface
Description Language,
IDL)。而根据HTTP协议的REST设计里,一般选择的就是伸手与响应的Header来呈现HATEOAS原则(具体请参见:https://en.wikipedia.org/wiki/HATEOAS)。那里也包罗那样一层含义:REST应尽可能地运用HTTP标准中存活的事物,例如Header、标准措施与状态码。

从正规的角度看,HTTP标准是一项RFC标准,世界认同;而其余自定义的SOA标准则可能是一项个人正式仍旧商店正式,最多是一项互联网草案(那对一大半商家来说都不可以),而一项专业愈来愈被广为认可接受,其完结的通用性就越强。个人正式和集团规范都五花八门,那样对每一个正式都要参照其连带文档完毕相应的表现逻辑是很费劲的。

2.3 安全性

一个方式被调用1次与被调用0次是相同的,此办法就是平安的,否则就是不安全的。例如,一个方法A仅仅是读取数据,并不成立或者涂改数据,不论A方法被调用多少次,都畸形数据记录暴发其余影响,A方法是高枕无忧的。而只要有另一个格局B对数码举办删除,B方法被调用1次后,数据会被删去(或者标识位被涂改),系统里的多寡暴发了转移,那么B方法是不安全的。

2.4 幂等性

一个办法被同样地调用1次与被调用数次是同一的,即一律的输入会赢得一致的输出,此方法就是幂等的,否则就不是幂等的。

2.3节中A方法与B方法都是幂等的,一个康宁的主意肯定是幂等的,一个幂等的法门不自然是平安的。

倘诺一个方法C对某个全局计数器执行自增操作并写入数据库,每一回调用C方法都会对系统数据暴发潜移默化,那么C方法就不是幂等的。

3 URL命名

URL用于标识资源,由此URL应该以名词举行命名,例如/usersjson,,
/users/children等。

一般URL会内嵌参数,例如要获得id为313的user的音讯,那么URL应该为/users/313,前边的user采取复数,若是要列出其兼具后代,则URL应为/users/313/children,children为复数格局,若是要拿走其id为499的后生,则URL应为/users/313/children/499

4 信息实体

音信实体,就是请求和响应音信中的entity-body(也称之为body),信息实体选择JSON字符串格式。

5 请求

5.1 方法

利用HTTP标准定义的乞求方法。

5.1.1 get

收获资源,单个参数一般写在URL上,几个参数则作为query
parameter附在URL后边,例如:

  • 单个参数:/user/123, 表示id为123的user

  • 五个参数:/user?name=tom&phone=13787890987&gender=male

get方法应为幂等的,并且不对数据记录发生影响。对于汉字与特殊字符,应该展开urlencode。

5.1.2 post

成立资源,请求的headers里安装Content-typeapplication/json,参数为json类型。

根据预定,在开创成功未来,重临的状态码应该是201(Created),并且在response的Header里设置Location为新创制的资源的URL,例如,成立了一个新的user,该user创设后id为888,那么Header里应该设置Location/users/888,当然,那应该是一个完整的URL,那里只是给出了一个相对路径的URI以作为验证。重临了这么些数据后,客户端可以自定义后续表现,或者查看创设后的user,或者刷新当前的user列表,这一个作为服务端并不关心。

如若重复提交了扳平的多寡,第三遍应该回到201,以后则应重回409(Conflict),并且在response的Header里设置Location指向已经存在的资源,表达争论的来源。

5.1.3 put

更新资源,对现有资源举行修改,请求的headers与post一样,参数也是。此情势应该是幂等的。

5.1.4 delete

删去资源。此措施应是幂等的。

5.2 Header

Content-type应设为application/json。

其余应设置一个version,指明所运用的接口版本。那不属于HTTP协议中的一片段,是自定义的,出于版本控制的勘查,具体见第七章。

5.3 body

利用JSON字符串,具体的布局有待商定,那不属于HTTP协议的一部分,是自定义的。

此地关键放置业务有关的数目。

6 响应

6.1 Header

根据响应的状态码不一样,相应地安装头部,具体见下一节。

不过在自己所了然的商家里,做法都是联合再次回到200,然后在回去的JSON字符串里安装音讯码。我是无法知道的。据一位前端同学说,前端代码接收到了请求以后,不便利获取Http状态码。其实我也写过前端,不深入,不过有的中心的学识或者有的,我觉着这并简单做到,估量是她的代码封装的时候没有设想到这或多或少,现在要改相比较麻烦,所以不想大动干戈、伤筋动骨。

6.2 状态码

状态码 语义 使用场景
200 OK 正常返回消息,什么问题也没有
201 Created 创建资源成功,Header里应设置Location指向新创建的资源
202 Accepted 请求已被接收,但是处理过程较长,不能马上返回结果
304 Not Modified 没有任何修改发生
401 Unauthorized 缺乏权限,指已经登录但是缺乏请求这个资源的权限
403 Forbidden 拒绝访问,可用于未登录时拦截返回的状态码,此时Header里应设置Location为登录页面的URL
404 Not Found 不存在所请求的资源
406 Not Acceptable 请求没有被接收,参数约束校验不通过,或者其他业务类型的错误都可以返回这个状态码,response的body里应有表示错误信息的JSON实体。
409 Conflict 请求的资源有冲突,例如多次提交一样的创建请求,response的Header里应设置Location为产生冲突的资源的URL
500 Internal Server Error 服务器的非业务类错误,response的body里应有表示错误信息的JSON实体

6.3 body采用JSON字符串。

JSON的构造分为三种:成功、失利。

貌似而言,唯有重返200的时候才要求读取成功的JSON,只有重返406和500的时候才须求读取失利的JSON,对于其他的状态码,客户端不须求服务器提供额外的音信。

对于成功的JSON,里面应该只包含一个result对象,而败诉的JSON应该利用那样的协会:

{

error: {

code: xxx,

message: "xxx",

data: {...}

}

}

破产的JSON唯有一个error对象,包罗错误码、音信及有关数据,message应该是平素可读的信息,客户端毋需明白发生了怎样错误,客户端只需将信息呈现出来即可。在吸收406的时候,客户端只需了解发生的一无所能是由客户端造成的即可,具体是怎么着类型并不须要知道,将音信直接突显出来,让动用的人知道是什么样即可,所以message应该是人类可以领略的文本。同理,收到500的时候,只需清楚那些荒唐是服务端的问题即可,客户端也毋需知道具体的一无所能类型,最多就将错误码和音信突显出来,让使用者有反映的依照即可。

7 版本控制

考虑到接口有可能提拔,升级的连串有三种:

  1. 增产作用接口

  2. 原本接口再次回到数据扩展字段

  3. 幸存接口重返数据变动现有字段格式或删除现有字段

  4. 现有接口变更业务逻辑

  5. 删去接口

里面,前二种升级并不会潜移默化客户端,由此毋需处理。而背后三种会促成使用旧接口的客户端无法健康办事。

诚如服务端升级与客户端升级都不是共同的,客户端升级往往会落后,由此在服务端升级后应当保留旧版本的接口继续运行一段时间,让未升高的客户端可以一连做事一段时间,同时可以上线新本子的客户端。过一段时间后再将旧版本的接口下线。

而版本控制应该是向下包容的,即假设当前版本是1.2,如若客户端请求1.3本子的劳动,应当用当下版本提供服务。倘诺没有注解请求的本子号,应当提供当前版本的劳动。

貌似情形下,客户端请求需求带版本号,不过服务端并不需求对此开展拍卖,除非是还要运行新旧版本的同一个接口,才须求做差距处理。

8 实现

8.1 Spring HATEOAS

Spring HATEOAS可以很方便地与Spring
MVC结合来开发RESTful接口。具体参照其文档:

http://docs.spring.io/spring-hateoas/docs/0.20.0.RELEASE/reference/html/\#fundamentals.jaxb-json

初稿链接:
https://bungder.github.io/2017/07/24/REST/

我的技艺博客:
https://bungder.github.io


何以简书的马克Down不辅助表格语法……

相关文章

网站地图xml地图