RESTful风格学习小记

时间:2019-11-10
本文章向大家介绍RESTful风格学习小记,主要包括RESTful风格学习小记使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

参考资料:(1)https://maimai.cn/article/detail?fid=1362221525&efid=iwXvSE_vD9dNRUX_dboP1g(2)http://www.ruanyifeng.com/blog/2011/09/restful.html  (3)https://www.cnblogs.com/duhuo/p/4245202.html

1、概念

RESTful不是一种技术,而只是一种API接口设计规范。凡是符合该规范的设计,都可以认为RESTful风格的服务。

但是由于各开发人员对RESTful的理解存在误区或者业务特殊场景,因此实际生产的环境中真正完全满足RESTful风格的服务并不多,也没有必要。但是在实际的应用中,有RESTful标准可以参考,是十分有必要的。

实际上在工作中,只要对api的接口规范、命名规则、返回值、授权验证等进行一定的约束,一般的项目api只要满足 调试、足够安全、风格一致可读性强、对于调用端没有歧义、我觉得就够了。接口是个开放人员看的,而不是给普通用户去调用的。

2、REST与RESTful

2.1 REST(Representational State Transfer)

REST:即表征状态转移,是一种互联网软件的架构原则。如果一个架构符合REST原则,那么它就是RESTful架构

要理解RESTful就要好好的理解下REST的具体含义。

(1)资源(Resource)

REST的名称“表现层状态转移”中的,表现层其实指的的是“资源(Resource)”的表现层。

所谓的资源其实就是,网络上的一个实体,或者是网络上的一个具体信息。可以是一段文本、一张图片、一首歌曲、一种服务。你可以使用一个URI(统一资源定位符)指向它。每种资源对应一个特定的URI。

所谓的“上网”,就是与互联网上的一系列“资源”互动,调用他的URI。

(2)表现层

“资源”是一种信息实体,可以多种外在的表现形式。我们将“资源”具体呈现出来的形式,叫做它的“表现层”(Representational )

比如:文本可以用txt格式表示,也可以用HTML、XML、JSON,甚至是二进制格式图片可以用JPG、PNG表示。

URI只代表资源的实体位置,而不代表他的展现形式。严格的说,有些网页最后的".html"后缀名, 其实是不必要的,因为这个后缀名表示格式,属于”表现层“的范畴。因此它的具体表现形式应该在HTTP的请求头信息中用AcceptContent-Type字段指定。

这两个字段才是对表现层的描述。

(3)状态转化(State Transfer)

访问一个网站,就代表客户端和服务器的一个互动过程,在这个过程中势必涉及到数据和状态的变化。

HTTP协议是一个无状态的协议。这也就意味着,所有的状态都存放在服务端。因此客户要想操作服务器,就必须以某种手段,让服务器发生状态转化(state transfer)。而这种转化是建立在表现层之上的,所以就是”表现层状态转化“。

客户端用到的手段吗,只能是HTTP协议。具体来说就是,使用HTTP协议里的四个表示操作方式的动词:GET、POST、PUT、DELETE。他们分别对应四种基本操作。GET(获取资源)、POST(新建或者更新资源资源,新建时不具备幂等性)、PUT(更新资源)。

DELETE(删除资源)

2.2 RESTful概述

综上2.1所述:总结一下什么是RESTful架构

(1)每一种URI代表一种资源

(2)客户端与服务端之间,具备传递这种资源的表现层

(3)客户端通过HTTP的四个动词,对服务器资源进行操作。实现表现层的状态转化。

2.3 RESTful六大原则

也即是REST之父阐述的REST六大原则

(1)C-S架构

数据存储在C-S端,C端只需要使用就可以。两端彻底分离的好处使得C端代码的可移植性变强,Server端额可拓展性变强。两端独立开发,互不干扰。

(2)无状态

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

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

(3)统一的接口

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

(4)一致的数据格式

服务端返回的数据格式要么是XML,要么是Json(获取数据),或者直接返回状态码,有兴趣的可以看看博客园的开放平台的操作数据的api,post、put、patch都是返回的一个状态码 。

自我描述的信息,每项数据应该是可以自我描述的,方便代码去处理和解析其中的内容。比如通过HTTP返回的数据里面有 [MIME type ]信息,我们从MIME type里面可以知道数据的具体格式,是图片,视频还是JSON,客户端通过div内容、查询串参数、请求头和URI(资源名称)来传送状态。服务端通过div内容,响应码和响应头传送状态给客户端。这项技术被称为超媒体(或超文本链接)。

除了上述内容外,HATEOS也意味着,必要的时候链接也可被包含在返回的div(或头部)中,以提供URI来检索对象本身或关联对象。下文将对此进行更详细的阐述。

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

(5)可缓存

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

(6)按需编码、可定制代码(可选)

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

2.4 RESTful的最佳实践

(1)版本

如github开放平台 http://developer.github.com/v3/
就是将版本放在url,简洁明了,这个只有用了才知道,一般的项目加版本v1,v2,v3?好吧,这个加版本估计只有大公司大项目才会去使用。但是一般是将请求版本号放在header里面

(2)参数命名规范

query参数可以采用驼峰命名方法,也可以采用下划线的命名方式。

例如:

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,冗余没有意义,形式不固定,不同的开发者还需要了解文档才能调用。

但是一般实践中,像管理后台经常通过在url末尾加上add/delete/update/list方式来区分接口(这样也有一定的可读性)

如:

 规范化后的RESTful风格的url,形式固定,可读性强。根据名词以及http请求动词就可以判断与操作这些资源

 (4)返回的数据格式统一

对于合法的请求应该统一返回数据格式,这里演示的是json

  • 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格式

返回失败的响应json格式

 当然,也可以根据自己业务的实际情况进行扩展,笔者所在的业务部门,统一的返回格式如下:

{
  errno:0,//错误码,0为成功,其他为失败(接口报错,服务不可用)
  msg:**,//错误提示信息,一般不展示给用户。前端可以根据这个信息做相应的逻辑处理
  showMsg:**, // 错误展示信息,一般是用来展示给用户的
  errTag:SUCCESS或者FAIL,//一般用来标记状态是否成功
  data:**,//返回数据,一般放在这个data字段里。若无数据返回,则置为null值
}

这个可以在后端代码中进行相应的封装,在controller层返回的时候调用实例化包装对象即可。

(5)HTTP状态码

一般通过Response响应头中的状态码也可以知道自己的请求是否成功。(4)中统一返回的状态码是对HTTP状态码的一个细分。

 常见的HTTP状态码如下:

  • 1**请求未成功
  • 2**请求成功、表示成功处理了请求的状态代码。
  • 3**请求被重定向、表示要完成请求,需要进一步操作。通常,这些状态代码用来重定向。
  • 4** 请求错误这些状态代码表示请求可能出错,妨碍了服务器的处理。                                                                                                                                                                                                                                                                         404:页面不存在或已经删除。                                                                                                                                                                                                                                                                                                                                                               403:资源不可用,服务器理解客户的请求,但拒绝处理它,通常由于服务器上文件或目录的权限设置导致的WEB访问错误。                                                                                                                                                                                                           405表示不允许使用该类型方法进行请求。
  • 5**(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。                                                                                                                                                                                                         502 :Bad Gateway是指错误网关,无效网关。它通常并不意味着上游服务器已关闭(无响应网关/代理) ,而是上游服务器和网关/代理使用不一致的协议交换数据。                                                                                                                                                     504 :错误代表网关超时 (Gateway timeout),是指服务器作为网关或代理,但是没有及时从上游服务器收到请求。

(6) 合理使用query parameter

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

关于分页,看看博客园开放平台分页获取精华区博文列表
http://api.cnblogs.com/api/blogposts/@picked?pageIndex={pageIndex}&pageSize={pageSize}
返回示例:
[ 
{
“Id”: 1,
“Title”: “sample string 2”,
“Url”: “sample string 3”,
“Description”: “sample string 4”,
“Author”: “sample string 5”,
“BlogApp”: “sample string 6”,
“Avatar”: “sample string 7”,
“PostDate”: “2017-06-25T20:13:38.892135+08:00”,
“ViewCount”: 9,
“CommentCount”: 10,
“DiggCount”: 11
},
{
“Id”: 1,
“Title”: “sample string 2”,
“Url”: “sample string 3”,
“Description”: “sample string 4”,
“Author”: “sample string 5”,
“BlogApp”: “sample string 6”,
“Avatar”: “sample string 7”,
“PostDate”: “2017-06-25T20:13:38.892135+08:00”,
“ViewCount”: 9,
“CommentCount”: 10,
“DiggCount”: 11
}
]

原文地址:https://www.cnblogs.com/yuerugou54/p/11830886.html