Fork me on GitHub

RESTful

RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务使能接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。 

相关定义

REST

REST(英文:Representational State Transfer,中文:表述性状态转移,简称REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,Roy Fielding是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。 

原则条件

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。
Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。

在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POSTDELETEHypermedia 是应用程序状态的引擎,资源表示通过超链接互联。

特点

RESTFUL特点包括:
1、每一个URI代表1种资源;作为资源标识的URI具有“可读性”,具有可读性的URI更容易被使用,使用者一看就知道被标识的是何种资源。
2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;(REST服务中虽然建议使用HTTP协议中四种标准方法POST、DELETE、PUT、GET来分别实现常见的“增删改  查”,但实际中,我们一般情况直接用POST来实现“增改”,GET来实现“删查”即可(DELETE和PUT甚至     会被一些防火墙阻挡)。)
3、通过操作资源的表现形式来操作资源;
4、资源的表现形式是XML或者HTML;

5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。

看Url就知道要什么
看http method就知道干什么
看http status  code就知道结果如何

RESTful与 RPC

使用 RPC 样式架构构建的基于 SOAP 的 Web 服务成为实现 SOA 最常用的方法。RPC 样式的 Web 服务客户端将一个装满数据的信封(包括方法和参数信息)通过 HTTP 发送到服务器。服务器打开信封并使用传入参数执行指定的方法。方法的结果打包到一个信封并作为响应发回客户端。客户端收到响应并打开信封。每个对象都有自己独特的方法以及仅公开一个 URI 的 RPC 样式 Web 服务,URI 表示单个端点。它忽略 HTTP 的大部分特性且仅支持 POST 方法。
由于轻量级以及通过 HTTP 直接传输数据的特性,Web 服务的 RESTful 方法已经成为最常见的替代方法。可以使用各种语言(比如 Java 程序、Perl、Ruby、Python、PHP 和 Javascript[包括 Ajax])实现客户端。RESTful Web 服务通常可以通过自动客户端或代表用户的应用程序访问。但是,这种服务的简便性让用户能够与之直接交互,使用它们的 Web 浏览器构建一个 GET URL 并读取返回的内容。
在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、POST、PUT、DELETE,还可能包括 HEAD 和 OPTIONS。
在 RPC 样式的架构中,关注点在于方法,而在 REST 样式的架构中,关注点在于资源 —— 将使用标准方法检索并操作信息片段(使用表示的形式)。资源表示形式在表示形式中使用超链接互联。
Leonard Richardson 和 Sam Ruby 在他们的著作 RESTful Web Services 中引入了术语 REST-RPC 混合架构。REST-RPC 混合 Web 服务不使用信封包装方法、参数和数据,而是直接通过 HTTP 传输数据,这与 REST 样式的 Web 服务是类似的。但是它不使用标准的 HTTP 方法操作资源。它在 HTTP 请求的 URI 部分存储方法信息。好几个知名的 Web 服务,比如 Yahoo 的 Flickr API 和 Delicious API 都使用这种混合架构。

RESTful架构

RESTful架构是对MVC架构改进后所形成的一种架构,通过使用事先定义好的接口与不同的服务联系起来。在RESTful架构中,浏览器使用POST,DELETE,PUT和GET四种请求方式分别对指定的URL资源进行增删改查操作。因此,RESTful是通过URI实现对资源的管理及访问,具有扩展性强、结构清晰的特点。
RESTful架构将服务器分成前端服务器和后端服务器两部分,前端服务器为用户提供无模型的视图;后端服务器为前端服务器提供接口。浏览器向前端服务器请求视图,通过视图中包含的AJAX函数发起接口请求获取模型。
项目开发引入RESTful架构,利于团队并行开发。在RESTful架构中,将多数HTTP请求转移到前端服务器上,降低服务器的负荷,使视图获取后端模型失败也能呈现。但RESTful架构却不适用于所有的项目,当项目比较小时无需使用RESTful架构,项目变得更加复杂。
 
 

RESTful6大原则

REST之父Roy Fielding在论文中阐述REST架构的6大基本原则,它们分别是:

1. C-S架构

数据的存储在Server端,Client端只需使用就行。两端彻底分离的好处使client端代码的可移植性变强,Server端的拓展性变强。两端单独开发,互不干扰。

2. 无状态

http请求本身就是无状态的,基于C-S架构,客户端的每一次请求带有充分的信息能够让服务端识别。请求所需的一些信息都包含在URL的查询参数、header、div,服务端能够根据请求的各种参数,无需保存客户端的状态,将响应正确返回给客户端。无状态的特征大大提高的服务端的健壮性和可拓展性。

当然,这种无状态性的约束也是有缺点的,客户端的每一次请求都必须带上相同重复的信息确定自己的身份和状态,造成传输数据的冗余性,但这种确定对于性能和使用来说,几乎是忽略不计的。

3.统一的接口

REST架构的核心内容,统一的接口对于RESTful服务非常重要。客户端只需要关注实现接口就可以,接口的可读性加强,使用人员方便调用。

REST接口约束定义为:资源识别; 请求动作; 响应信息; 它表示通过uri标出你要操作的资源,通过请求动作(http method)标识要执行的操作,通过返回的状态码来表示这次请求的执行结果。

4.一致的数据格式

服务端返回的数据格式要么是XML,要么是Json(获取数据),或者直接返回状态码,一些知名网站的开放平台的操作数据的api,post、put、patch都是返回的一个状态码 。

如请求一条微博信息,服务端响应信息应该包含这条微博相关的其他URL,客户端可以进一步利用这些URL发起请求获取感兴趣的信息,再如分页可以从第一页的返回数据中获取下一页的URT也是基于这个原理。

5.可缓存

在万维网上,客户端可以缓存页面的响应内容。因此响应都应隐式或显式的定义为可缓存的,若不可缓存则要避免客户端在多次请求后用旧数据或脏数据来响应。管理得当的缓存会部分地或完全地除去客户端和服务端之间的交互,进一步改善性能和延展性。

6.按需编码、可定制代码

服务端可选择临时给客户端下发一些功能代码让客户端来执行,从而定制和扩展客户端的某些功能。比如服务端可以返回一些 Javascript 代码让客户端执行,去实现某些特定的功能。提示:REST架构中的设计准则中,只有按需编码为可选项。如果某个服务违反了其他任意一项准则,严格意思上不能称之为RESTful风格。

 

最佳示例

1. 版本控制

如github开放平台的API: 可以发现,一般的项目加版本v1,v2,v3版本号,为的是兼容一些老版本的接口,这个加版本估计只有大公司大项目才会去使用。

2.参数命名规范

query parameter可以采用驼峰命名法,也可以采用下划线命名的方式,推荐采用下划线命名的方式,据说后者比前者的识别度要高,其中,做前端开发基本都后后者,而做服务器接口开发基本用前者。

http://example.com/api/users/today_login 获取今天登陆的用户
http://example.com/api/users/today_login&sort=login_desc 获取今天登陆的用户、登陆时间降序排列

  

3.url命名规范

API 命名应该采用约定俗成的方式,保持简洁明了。在RESTful架构中,每个url代表一种资源,所以url中不能有动词,只能有名词,并且名词中也应该使用复数。实现者应使用相应的Http动词GET、POST、PUT、PATCH、DELETE、HEAD来操作这些资源即可

不规范的的url,冗余没有意义,形式不固定,不同的开发者还需要了解文档才能调用。

http://example.com/api/getallUsers       //GET 获取所有用户
http://example.com/api/getuser/1          //GET 获取标识为1用户信息
http://example.com/api/user/delete/1    //GET/POST 删除标识为1用户信息
http://example.com/api/updateUser/1   //POST 更新标识为1用户信息
http://example.com/api/User/add         //POST添加新的用户

  规范后的RESTful风格的url,形式固定,可读性强,根据users名词和http动词就可以操作这些资源。

http://example.com/api/users               //GET 获取所有用户信息
http://example.com/api/users/1           //GET 获取标识为1用户信息
http://example.com/api/users/1          //DELETE 删除标识为1用户信息
http://example.com/api/users/1         //Patch 更新标识为1用户部分信息,包含在div中
http://example.com/api/users           //POST 添加新的用户

  

4,统一返回数据格式

对于合法的请求应该返回统一的数据格式,对于返回数据,通常会包含如下字段。 - code——包含一个整数类型的HTTP响应状态码。 - status——包含文本:”success”,”fail”或”error”。HTTP状态响应码在500-599之间为”fail”,在400-499之间为”error”,其它均为”success”(例如:响应状态码为1XX、2XX和3XX)。这个根据实际情况其实是可要可不要的。 - message——当状态值为”fail”和”error”时有效,用于显示错误信息。参照国际化(il8n)标准,它可以包含信息号或者编码,可以只包含其中一个,或者同时包含并用分隔符隔开。 - data——包含响应的div。当状态值为”fail”或”error”时,data仅包含错误原因或异常名称、或者null也是可以的。

例如,返回成功的响应json格式:

{
  "code": 200,
  "message": "success",
  "data": {
    "userName": "123456",
    "age": 16,
    "address": "beijing"
  }
}

  返回失败的响应json格式:

{
  "code": 401,
  "message": "error  message",
  "data": null
}

  

5. http状态码

HTTP状态码也是有规律的:

1,请求未成功 2,请求成功、表示成功处理了请求的状态代码。 3,请求被重定向、表示要完成请求,需要进一步操作。通常,这些状态代码用来重定向。 4, 请求错误这些状态代码表示请求可能出错,妨碍了服务器的处理。 5,(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。

6. 合理使用query parameter

在请求数据时,客户端经常会对数据进行过滤和分页等要求,而这些参数推荐采用HTTP Query Parameter的方式实现。

//比如设计一个最近登陆的所有用户
http://example.com/api/users?recently_login_day=3

//搜索用户,并按照注册时间降序
http://example.com/api/users?recently_login_day=3

//搜索用户,并按照注册时间升序、活跃度降序
http://example.com/api/users?q=key&sort=create_title_asc,liveness_desc

  

7. 多表、多参数连接查询设计URL

在做单个实体的查询比较容易和规范操作,但是在实际的API并不是这么简单而已,因为常常会设计到多表连接、多条件筛选、排序等。

比如我想查询一个获取在6月份的订单中大于500元的且用户地址是北京,用户年龄在22岁到40岁、购买金额降序排列的订单列表,那么接口可能如下:

http://example.com/api/orders?order_month=6&order_amount_greater=500&address_city=北京&sort=order_amount_desc&age_min=22&age_max=40

  

从这个URL上看,参数众多、调用起来还得一个一个仔细对着,而且API本身非常不容易维护,命名看起来不是很容易,不能太长,也不能太随意。

在.net WebAPI中,我们可以使用属性路由,属性路由就是将路由附加到特定的控制器或操作方法上装饰Controll及其使用[Route]属性,一种定义路由的方法称为属性路由。

这种好处就是可以精准地控制URL,而不是基于约定的路由,简直就是为这种多表查询量身定制似的的。从webapi 2开发,现在是RESTful API开发中最推荐的路由类型。

[Route(“api/orders/{address}/{month}”)]

  而Action中的查询参数就只有金额、排序、年龄。减少了查询参数、API的可读性和可维护行增强了。

http://example.com/api/orders/beijing/6?order_amount_greater=500&sort=order_amount_desc&age_min=22&age_max=40

  所以,在向别人介绍rest的时候,首先需要介绍服务背景,然后再介绍它的一些约束规则,切不可笼统介绍。

RESTful优缺点

  • 结构清晰、符合标准、易于理解、扩展方便
  •  提高可见性(可以单独考虑每个请求)
  •  提高了可靠性(更容易从局部故障中修复)
  •  提高可扩展性(降低了服务器资源使用)

优点是因为他对uri进行了限制,只用于定义资源。这样看起来比较容易理解。尤其是对简单的对象的增删改查,很好理解。

缺点是因为这种限制,导致设计uri变得复杂了。尤其是复杂的关系,操作,资源集合,硬性套用rest原则设计非常困难。在rest基础上的HATEOAS,返回的json里增加了相应的关系和url。这也同样带来问题。好处是对简单的关系,的确可以通过url进一步处理。但对复杂的关系和操作,HATEOAS并不能胜任描述。反而在单纯的数据中增加了一堆垃圾信息。

 

知乎:https://zhuanlan.zhihu.com/p/91240556

posted @ 2020-05-24 19:08  威威超酷  阅读(360)  评论(0编辑  收藏  举报