关于RESTFUL的理解
1、什么是REST
REST全称是Representtatinal State Transfer,中文意思是表述性状态转移。如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。这个架构并没有什么新的技术,其实就是对现有的web标准的一个更好的总结。但是理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。所谓的表述性状态转移,其实就是指的资源——任何事物,只要有被引用的必要,它就是一个资源。资源可以是实体(例如手机号码),也可以只是一个抽象概念(例如价值)。
资源有几个方面需要知道:资源与URI,统一资源接口,资源的表述,资源的链接,状态的转移
实际生活中什么是资源呢?比方说某用户的手机号码,某用户的个人信息这些实体信息,或者某手机号码的潜在价值也是可以被称作是资源,要是想让一个资源可以被识别,需要有一个唯一的标识,在web中这个唯一标识就是URI。URI既可以看成是资源的地址,也可以看成是资源的名称。如果某些信息没有使用URI来表示,那它就不能算是一个资源,只能算是资源的一些信息而已。URI的设计应该遵循可寻址性原则,具有自描述性,需要在形式上给人以直觉上的关联
URI的设计也是要符合相关的规则:1、使用_或-来让URI可读性更好。2、使用/来表示资源的层级关系。3、使用?用来过滤资源。4、,或;可以用来表示同级资源的关系
统一资源接口:RESTFul架构应该遵循统一接口原则,统一接口包含了一直受限的预定义的操作,不论什么样的资源,都是通过使用相同的接口进行资源的访问。接口应该使用标准的HTTP方法如GET,PUT和POST,并遵循这些方法的语义。统一资源接口要求使用标准的HTTP方法对资源进行操作,所以URI只应该来表示资源的名称,而不应该包括资源的操作。简单的说,URI不应该使用动作来描述,例如下面是一些不符合统一接口要求的URI:
GET/getUser/1
资源的表述:上面说的是通过HTTP方法可以获得资源,但是实际上,客户端获得的只是资源的表述而已。资源在外界的具体呈现,可以有多种表述(或称为表现、表示)形式,在客户端和服务端之间传送的也是资源的表述,而不是资源本身。例如文本资源可以采用html、xml、json等格式,图片可以使用PNG或JPG展现出来。资源的表述包括数据和描述数据的元数据。例如,HTTP头“Content-Type”就是这样一个元数据属性。
那么客户端怎么知道服务端提供的是那种表述形式呢?答案就是可以通过HTTP内容写上,客户端可以通过Accept头请求一种特定格式的表述,服务端则通过Content-Type高速客户端资源的表述形式。下面以github为例,请求某组织资源的json格式的表述形式;
Request
GET https://api.github.com/orgs/github HTTP/1.1
Accept:application/json
Response
HTTP/1.1 200 OK
Content-Type:application/json;charset=utf-8
{
"login":"github",
"id":1,
"url":"https://api.github.com/orgs/github",
"avatar_url":"https://github.com/images/error/octocat_happy.gif",
"name":"github",
"company":"Github",
"blog":"https://github.com/blog",
"location":"San Francisco",
"email":"octocat@github.com",
"public_repos":2,
"public_gists":1
"followers":20,
"following":0,
"html_url":"https://github.com/octocat",
"created_at":"2008-01-14T04:33:35Z",
"type":"Organization"
}
假如github也能够支持xml格式的表述格式,那么结果就是下面这样
#request
GET https://api.github.com/orgs/github HTTP/1.1
Accept:text/html
#response
HTTP/1.1 200 OK
Content-Type:text/xml;charset=utf-8
还是建议使用上面描述的内容协商的方式来区分表述格式
当服务器不支持所请求的表述格式,它应该返回一个HTTP406响应,表示拒绝处理该请求
资源的链接:就是在表述格式里面加入链接来引导客户端,增强资源的连通性。例子如下:
#Request
GET https://api.github.com/orgs/github/repos HTP/1.1
Accpet:application/json
#Response
HTTP/1.1 Status:200 OK
Link:<https://api.github.com/orgs/github/repos?page=2>;rel="next"
<https://api.github.com/orgs/github/repos?page=3>;rel="last"
Content-Type:application/json;charset=utf-8
[{
"id":129669,
"owner":{
"login":"octocat",
"id":1,
"avatar_url":"https://github.com/images/error/octocat_happ.gif",
"gravatar_id":"somehexcode",
"url":"https://api.github.com/users/octocat"
}
}]
状态的转移:REST原则中的无状态通信原则,并不是说客户端应用不能有状态,而是指服务端不应该保存客户端的状态。实际上,状态应该区分应用状态和资源状态,客户端负责维护应用状态,而服务端维护资源状态。而两者之间的交互是无状态的。可以通过“会话”改变这个状态。“会话”状态不是作为资源状态保存在服务端的,而是被客户端作为应用状态进行跟踪的。客户端应用状态在服务端提供的超媒体的指引下发生变迁。服务端通过超媒体告诉客户端当前状态有哪些后续状态可进入。这些类似下一页之类的链接起的就是这种推进状态的作用-----指引你如何从当前状态进入下一个可能的状态