您的位置:首页 > 运维架构 > 网站架构

restful架构风格设计准则(一)以资源为中心、自描述的请求响应、资源状态迁移为粒度

2017-09-21 09:27 330 查看
读书笔记,原文链接:http://www.cnblogs.com/loveis715/p/4669091.html,感谢作者!

一、需求描述

当用户在某个电子商务网站购物时,他首先查看要购买的商品分类,然后选择某个商品,查询其明细信息。

用户查询商品分类列表,系统显示商品分类列表(食品、服装、电器、文具、玩具)

用户选择分类明细,查询分类(佳宝、黑牛)

用户选择查看分类下的商品列表,系统显示分类下的商品列表(酸奶,纯牛奶)

二、业务流程

1、商品分类列表请求(食品、电器、文具、玩具)

1.1、请求

用户请求所有商品分类

GET /api/categories
Host: www.egoods.com
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Accept: application/json

1.2、响应

系统返回所有商品分类列表,该数组的每个元素包含了两部分信息:分类名称label 和 分类所对应URL,其中分类名称(Label)将显示给用户,而当用户根据分类名查看该分类,系统会根据分类对应URL并向该URL 发送请求,从而得到分类详细信息

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx

[
{
"label" : "食品",
"url" : "/api/categories/1"
}, {
"label" : "服装",
"url" : "/api/categories/2"
}
...
{
"label" : "电器",
"url" : "/api/categories/25"
}
]

2、商品分类明细查询(食品:佳宝、黑牛)

2.1、请求

用户请求分类1的明细信息。

GET /api/categories/1
Host: www.egoods.com
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Accept: application/json

2.2、响应

系统显示分类1的明细信息,包含了一个产品品牌列表。

响应属性列表

属性 url 标示了“Food”分类所对应的URL

属性 label 属性显示分类的名称

属性 items_url 标示获取属于食品分类的各个产品的URL

属性 brands 标示“食品”分类中的著名品牌列表,例如 佳宝,黑牛 等。每个品牌都拥有名称label,访问地址url等信息。根据这些属性,页面可以列出这些品牌名称,并允许用户点击跳转查询品牌所对应的信息。

Food分类还包含了其它一系列属性,如表示当前其它用户正在搜索的hot_searches属性等

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx

{
"url" : "/api/categories/1",
"label" : "Food",
"items_url" : "/api/items?category=1",
"brands" : [
{
"label" : "佳宝",
"brand_key" : "32073",
"url" : "/api/brands/32073"
}, {
"label" : "黑牛",
"brand_key" : "56632",
"url" : "/api/brands/56632"
}
...
],
"hot_searches" : …
}

3、商品分类下商品列表查询(食品::佳宝:酸牛奶)

3.1、请求

用户浏览佳宝品牌的商品列表:
GET /api/items?category=1&brand_key=56632
Host: www.egoods.com
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Accept: application/json

3.2、响应

...

三、REST 如何在业务中落地

1、REST 是什么?

REST是一种组织Web服务的架构,并不是一种新技术,也没有要求一定要使用HTTP,REST的目标是为了创建具有良好扩展性的分布式系统。

REST 作为一种架构,提出了一系列架构级约束,如:

客户/服务器模型:客户和服务器之间通过一个统一的接口来互相通讯。

层次化的系统:在一个REST系统中,客户端并不会固定地与一个服务器打交道。

无状态:在一个REST系统中,服务端并不会保存有关客户的任何状态。也就是说,客户端自身负责用户状态的维持,并在每次发送请求时都需要提供足够的信息。

可缓存:REST系统需要能够恰当地缓存请求,以尽量减少服务端和客户端之间的信息传输,以提高性能。

统一的接口:一个REST系统需要使用一个统一的接口来完成子系统之间以及服务与用户之间的交互。这使得REST系统中的各个子系统可以独自完成演化。

2、REST关键词:资源和资源的状态

资源是REST系统的核心概念,所有的设计都会以资源为中心,包括如何对资源进行添加,更新,查找以及修改等。资源本身则拥有一系列状态。在每次对资源进行添加 ,删除或修改的时候,资源就将从一个状态转移到另外一个状态。

每个资源都拥有一个资源标识。每个资源的资源标识可以用来唯一地标明该资源。

资源的自描述性。一个REST系统所返回的资源需要能够描述自身,并提供足够的用于操作该资源的信息,如如何对资源进行添加,删除以及修改等操作。也就是说,一个典型的REST服务不需要额外的文档对如何操作资源进行说明。

HATEOAS。即客户只可以通过服务端所返回各结果中所包含的信息来得到下一步操作所需要的信息,如:到底是向哪个URL发送请求等。一个典型的REST服务不需要额外的文档标示通过哪些URL访问特定类型的资源,而是通过服务端返回的响应来标示到底能在该资源上执行什么样的操作。一个REST服务的客户端也不需要知道任何有关哪里有什么样的资源这种信息。

3、REST如何在业务中落地

还是借助上面的例子:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx

{
"url" : "/api/categories/1",
"label" : "Food",
"items_url" : "/api/items?category=1",
"brands" : [
{
"label" : "友臣",
"brand_key" : "32073",
"url" : "/api/brands/32073"
}, {
"label" : "乐事",
"brand_key" : "56632",
"url" : "/api/brands/56632"
}
...
],
"hot_searches" : …
}

看看REST架构约束如何体现:

3.1、消息自描述性的体现

响应报文格式的自描述性

Content-Type: application/json 看到了该响应头中所标示的格式之后,消息接收方可以按照JSON的格式理解或分析该响应中的负载。这便是消息自描述性的一个体现。

在基于HTTP的REST系统中,我们可以通过使用HTTP标准功能来提高消息的自描述性。这些功能已被广大的软件开发人员所熟知,并得到了众多浏览器厂商以及Web类库的支持,根据这些标准实现REST服务具有较高的消息自描述性。

举例来说,如果在请求中标明了If-Modified-Since头,那么服务端将可能返回一个304 Not Modified响应。在看到该响应的时候,浏览器或其它浏览工具可以从缓存中取得上一次得到的结果。因此,在一个基于HTTP的REST系统中,如何准确地使用HTTP协议是一项非常重要的内容。

资源的自描述性

在上面的示例中,服务端响应使用JSON表示食品分类,该响应先通过label属性描述了自己是一个什么分类。接下来通过brands属性表示了该分类中的著名品牌,并通过hot_searches标示了在该分类中的热搜关键字。可以看到,该负载中的所有属性都清晰地描述了自身所表达的含义。

那在该资源表示中的url属性是什么意思?实际上这是为子约束“每个资源都拥有一个资源标识”所添加的一个属性。该子约束要求每个资源的资源标识可以用来唯一地标明该资源。

对于网络应用来说,资源标识就是URI。而在基于HTTP的系统中,最自然的资源标示是URL。在表示单个资源的时候,这个URL常常会包含着资源在该类资源中的ID。我们就将以这种方式来区分URL和ID:URL用来指向资源所在的地址,而ID则表示该资源在该类型资源中的ID。

子约束HATEOAS服务的体现

在用户看到items_url属性时,其就可以通过向该URL发送GET消息得到属于食品分类中的所有商品的列表。而在商品品牌的表示中也拥有一个url属性。也就是说,向该URL发送一个GET请求也能够得到相应品牌的详细信息。

同样地,既然在介绍HATEOAS时说REST服务并不需要文档来告诉用户哪里拥有什么样的资源,那用户应该如何知道向/api/categories发送GET请求就能得到所有的分类呢?标准的做法则是向/api直接发送一个GET请求:

GET /api
Host: www.egoods.com
Authorization: Basic xxxxxxxxxxxxxxxxxxx
Accept: application/json
而在返回的响应中将标示出REST API的版本以及所有可以访问的资源等信息:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx

{
"version": "1.0",
"resources": [
{
"label" : "Categories",
"description" : "Product categories",
"uri": "/api/categories"
}, {
"label" : "Items",
"description" : "All items on sell",
"uri": "/api/items"
}
]
}
可以看到,在该响应中列出了可以被访问的两种资源:表示商品分类的Categories以及表示商品的Items。在需要访问特定类型的资源时,软件开发人员可以通过直接向这两种资源所对应的URI发送GET请求即可。OK,相信现在大家已经了解了REST服务所提供的各种约束。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐