RESTful简介

RESTful

REST全称是Representational State Transfer,暂且理解为资源表现时的状态转化。它是由Roy Thomas Fielding提出来的一个架构原则。Fielding是个牛人,他是HTTP协议(1.0版和1.1版)的主要设计者,Apache服务器软件的作者之一。 他设计REST的目的是希望在符合架构原理的基础上,通过对以网络为基础的应用软件进行架构设计,得到一个功能强大、性能良好、适合通信的架构。RESTful最终能够拥有这些优点也就很自然了。


RESTful

理解RESTful

如果想要清楚的理解RESTful架构的话,必须要了解一些属于它的术语:

  • 资源与URI
  • 统一资源接口
  • 资源的表述
  • 资源的链接
  • 状态的转移

我们一起来看看这些术语。

资源与URI

RESTful的核心就是资源,所有可能被引用到的事物都可以成为资源。它可以是实际的数据或者信息:如姓名、编号、图片这样的单一数据,或是商品信息这样有详细内容的信息。它还可以是一个抽象的概念如逻辑或者价值:如两个事务处理的逻辑关系,或者一个问题的价值。了解了资源的概念,那如何表示这些资源呢?在RESTful的原则中是通过URI来作为唯一标识的。这里容易混淆的有一些信息如果它不用URI来表示,那我们就不把它当做资源,URI从设计的角度来说是要可寻址的。例如: - http://www.hubwiz.com/register - http://www.hubwiz.com/exchange - http://xb.hubwiz.com/sku/557fd4e96a16250d8c2a0b2d/0 - http://www.hubwiz.com/class/578dfbc816d03a7123dd6335

统一资源接口

有了资源那我们肯定是要引用或者改变这些资源,引用或者改变这些资源的时候就要用到接口。统一资源接口就是受限的预订的一组标准接口,无论你是什么资源,我们都这么访问。对于web实例中的http实现来说典型的接口就是:

  • GET
  • DELETE
  • PUT
  • POST

这些常用的接口都是幂等的,无论对资源进行多少次的请求,请求结果总是一样的。它们分别对应四种最基本的操作:GET用来获取资源,POST用来新建资源(也可以更新资源),PUT用来更新资源,DELETE用来删除资源。

在使用的时候,我们确定了那些是资源后就利用这些接口进行资源处理,处理时可以选择暴露一些资源以提供接口,同时隐藏无须暴露的内部资源。举个例子大家能更深刻的认识一下,如果我们做一个商品买卖的应用,那么商品就可以是一个资源命名为goods那针对这个资源我们就可以定义与他对应的API,用以操作这个资源,其RESTful的定义如下:

  • GET /goods # 获取商品的列表。
  • GET /goods/001212 # 查看具体的一个商品。
  • POST /goods # 新建一个商品。
  • PUT /goods/009192 # 更新009192号商品。
  • DELETE /goods/100012 #删除100012号商品。

能够将资源准确的拆分出来,并提供相应的接口是应用RESTful的最基础一步。

资源的表述

那什么是资源表述呢?以web应用来举例的话,资源在浏览器中主要是以html的形式来表达。这和资源的定义有很大的关系,不过对于一个RESTful的资源来说,它的表述形式可以是HTML、XML、JSON、TXT、EXCEL、PNG、JPG等等都行,如果你通过html形式获得了资源,只是说明你获得了它的html表述。小建议JSON是很多应用的最好表述,建议优先提供采用,另外就是

资源的表述包括了数据本身和描述数据的元数据,也就是说客户端需要获取什么样表述的数据可以向服务器说明,说明的描述就在元数据中。他们之间交流可通过http头来协商。

一个Json的表述示例如下:

比如如果请求的是商品类型这个资源的话,元数据中使用Accept描述了需要返回一个JSON的表述:

1
2
3
GET /api/categories
Host: www.egoods.com
Accept: application/json

这样服务端就会返回如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"label" : "食品",
"url" : "/api/categories/1"
}, {
"label" : "服装",
"url" : "/api/categories/2"
}
...
{
"label" : "电子设备",
"url" : "/api/categories/25"
}
]

如果需要其他的表述,也是一样的。

资源的链接

我们在使用web应用的时候,经常要从一个页面跳到另外一个页面,那这些跳转是如何实现的呢?其实本质上就是通过链接将一个一个的资源串起来,这就是所谓的超媒体(hypertext/Hypermedia)连通性。还以商品为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: xxx
{
"url": "/api/categories/2",
"label": "food",
"items_url": "/api/items?category=2",
"company":
[
{
"label": "老干妈",
"company_id" : "33323",
"url": "/api/company/33323"
}, {
"label": "伊利",
"company_id": "22221",
"url": "/api/company/22221"
}
...
]
}

上面的示例我们可以看到,这个资源内容中有一个url属性。对于网络应用来说,资源标识就是URI。那么在一个基于HTTP的系统web应用中,最自然的资源表示便是URL。在表示单个资源的时候,这个URL常常会包含着资源在该类资源中的ID,就是通过这种链接的方式,我们和资源联系了起来。

状态的转移

以URI为标志、以超文本或超媒体驱动的状态转移是REST架构核心。RESTful有一个基本的无状态原则,它的含义是指客户端和服务器交互的过程中(各次请求之间)是无状态的。特别强调一下“状态”指请求的状态,而不是资源的状态。

Restful风格的无状态约束要求服务器不保存请求状态,如果确实需要维持用户状态,也应由客户端来负责,这个也被叫做应用状态。也就说每一次请求你都要提供处理这个请求的一切信息,而处理完成后服务器会提供给你一个结果,这次请求就完成了,服务器不会再为你这次请求保存任何的请求状态,下一次发起请求的时候也是一样,还是需要提供所有信息。 最典型的是在身份认证的时候使用cookie的理解上,尽量使用SSL或者直接用https吧。

另外一个需要提到的就是HATEOAS(Hypermedia as the Engine of Application State的缩写形式),应用状态引擎。它所表达的意思是 客户端只可以通过服务端所返回各结果中所包含的信息来得到下一步操作所需要的信息,如到底是向哪个URL发送请求等。也就是说,一个典型的REST服务不需要额外的文档标示通过哪些URL访问特定类型的资源,而是通过服务端返回的响应来标示到底能在该资源上执行什么样的操作。一个REST服务的客户端也不需要知道任何有关哪里有什么样的资源这种信息。

附:

  • 可能的状态码含义

    • 201 (created)- 新的资源被创建 。
    • 301 (Moved Permanently)- 资源的URI已更改。
    • 303 (See Other)- 其他(如,负载均衡)。
    • 304 (not modified) - HTTP缓存有效。
    • 400 (bad request)- 指代坏请求如格式错误。
    • 401 (unauthorized) - 未授权。
    • 403 (forbidden) - 鉴权成功,但是该用户没有权限。
    • 404 (not found)- 请求的资源不存在。
    • 405 (method not allowed) - 该http方法不被允许。
    • 406 (not acceptable)- 服务端不支持所需表示。
    • 409 (conflict)- 通用冲突。
    • 410 (gone) - 这个url对应的资源现在不可用。
    • 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)。
    • 415 (unsupported media type)- 请求类型错误。
    • 422 (unprocessable entity) - 校验错误时用。
    • 429 (too many request) - 请求过多。
    • 500 (internal server error)- 通用错误响应。
    • 503 (Service Unavailable)- 服务当前无法处理请求。
  • GET

    • 200(OK) - 表示已在响应中发出
    • 204(无内容) - 资源有空表示
  • POST

    • 200(OK)- 现有资源已被更改
    • 202(accepted)- 已接受处理请求但尚未完成(异步处理)
  • PUT

    • 200 (OK)- 已存在资源被更改
  • DELETE

    • 200 (OK)- 资源已被删除