REST的全称是Representational State Transfer


REST是一种区别于传统MVC的,针对网络应用的设计和开发模式


采用REST可以有效降低开发的复杂性,并极大的提高系统的可伸缩性



REST的特性:


1、网络上的所有事物都要被抽象为资源(resource):


要想理解REST,首先要理解什么是“资源”


这里所说的“资源”,所指的并不是单纯意义上的数据,而是数据+特定的表现形式(representation)


例如,“本月卖得最好的10本书”和“你最喜欢的10本书”在数据上可能有重叠:即有一本书既卖得好,你又喜欢。


但是,由于这本书所属于的representation不同,因此是不同的资源。


下面是一些REST的resouce实例:


ID为10000的用户

在用户最喜欢的书籍中,排名在第10位的书

2012年11月份中,ID为15462的订单

2012年11月的所有订单

生成2012年11月份的订单报表


从上面的示例中可以看出,无论是单一数据项、数据项集合、虚拟亦或实际的对象、计算结果甚至流程等,都可以视为应用中的resouce。



2、每个资源对应一个唯一、通用的资源标识(resource identifier):


在REST中,每个资源都应该是可标识的,都应该拥有一个明显的资源标识。


在RESTful HTTP中,使资源获得唯一、通用的资源标识的方式就是使用URI来标识它


下面是一些resouce identifier的实例(对应着上面的resouce)

http://example.com/customer/10000

//ID为10000的用户

http://example.com/books/favourites/10

//在用户最喜欢的书籍中,排名在第10位的书

http://example.com/orders/2012/11/15462

//2012年11月份中,ID为15462的订单

http://example.com/orders/2012/11

//2012年11月的所有订单

http://example.com/processes/order-report/2012/11

//生成2012年11月份的订单报表

标识所有值得标识的事物,领会这个观念可以进一步引导你创造出在传统的应用程序设计中不常见的资源。



3、使用通用资源标识来表示一切资源:


首先观察下面这个虚构的XML片段:



<order self="http://example.com/customers/1234"> 
   <amount>23</amount> 
   <product ref="http://example.com/products/4554"> 
      <customer ref="http://example.com/customers/1234" />
   </product>
</order>

在传统模式中,我们会通过简单的“id”属性来指定product和customer的值


这样的缺点很明显:product和customer所指向的实例对象必须处于应用环境之内


而使用URI来表示资源的话,由于URI的命名规范是全球标准


因此就可以指向由不同应用、不同服务器甚至位于另一个大陆上的不同公司提供的资源。



4、仅使用标准方法对资源进行操作:


在REST中,所有的资源都继承自同一个接口,这个接口定义了可以对这些资源可以进行的操作


以传统的HTTP规范为例,大家熟知HTTP请求中包含GET、POST、PUT和DELETE四种类型,这些方法的含义连同行为许诺都一起定义在HTTP规范之中


想象一下RESTful HTTP方案,该方案中的所有资源都应当继承自类似于这样的一个接口,以下是接口的伪代码示例:


class Resource {
     Resource(URI u);
     Response get();
     Response post(Request r);
     Response put(Request r);
     Response delete();
}

这样定义的好处是,客户端与服务器之间完全不需要事先定义好交互的接口,就可以有目的地通过接口进行协作


因为客户端知道服务器端所有的资源都可以通过URI来创建和访问,并且都只提供了get、post、put和delete四个接口


下面看这个非REST的简单的采购方案的例子:


Resin 版本怎么看_HTTP


从这个例子中可以很明显的看到,每个服务中都包含了许多不同的方法,并且这些方法的名字不尽相同


这也就意味着:如果客户端试图使用这些服务,那它必须针对这些特定接口进行编码——不可能在这些接口定义之前,使用客户程序去有目的地和接口协作。


如果采用REST的方式重新设计此方案的话,该方案的结构就是这样的:


Resin 版本怎么看_客户端_02


从这个例子中可以很明显的看到,所有资源都实现了标准的GET、PUT、POST和DELETE方法,并且该方法都符合其名称所表述的意义



对比以上两个例子,我们就可以看出非REST和REST在设计思想上本质的区别:


在非REST的设计中,应用拥有着固定数量的服务,其中每个服务都提供了许多不同的方法。


而在REST的设计中,应用拥有着数量众多的资源,但每个资源提供的方法都是固定的。



5、每个标准方法的实现都严格遵守约定的行为规则:


继续以RESTful HTTP为例,接口中每个方法的行为都有相关的约定:


GET:表示“获取一个资源”,GET方法不会对服务器的数据造成任何改变,因此你可以重复调用GET方法来获取资源


POST:表示“创建一个新资源”,POST方法会对服务器的数据造成改变,并且重复调用的时候会重复创建资源,因此需要慎重调用它。


PUT:表示“更新资源数据”,如果资源不存在的话,PUT方法会根据URI创建一个新的资源,但是你可以重复调用PUT方法来更新资源,这不会有任何问题。


DELETE:表示“删除一个资源”,如果资源不存在的话,DELETE不会执行任何操作,因此DELETE方法也是可以被重复调用的。


若每个资源中,对标准方法的实现都符合以上的行为规则的话,那么客户端就知道哪些方法可以去放心的调用,哪些方法需要慎重的调用,并且调用这些方法可以实现哪些行为



6、无状态通信(stateless)


这里的stateless表示的是,服务器端不能保持除了单次请求之外的,任何与其通信的客户端的通信状态。


但这并不是说在整个WEB应用中不能有状态,而是要求状态要么被放入资源的状态中,要么保存在客户端上。


这样做的好处显而易见:首先服务器不再需要保持客户端状态,因此可以极大的节省服务器端的内存可用空间


其次在分布式服务器上,客户端两次连续的请求中可能访问的并不是同一台服务器,但是只要你传递的资源标识是相同的,那么返回的资源就一定是相同的。



综上所述:REST架构的特点可以简单归结为:


整个系统都是由资源组成的,每个资源都对应着一个唯一的资源标识,所有的资源都对外提供相同的接口,每个接口的行为都有相关的约定,并且服务器端不保存客户端的任何状态

REST、RESTful HTTP与HTTP的关系:


先前不止一次地出现了RESTful HTTP这个词语,实际上HTTP、RESTful HTTP和REST它们三者的关系是怎样的呢?


首先,REST只是一个非常抽象的概念,它只是一种设计模式,只要符合以上几条核心思想的程序架构,都可以视作是REST的。


而HTTP则是REST风格的一个主要实现,它已经形成了具体的一套标准。但是许多使用HTTP的应用并没有遵循REST原则:例如使用HTTP GET调用诸如添加、删除对象的操作。


因此,从字面意思上理解,RESTful HTTP就是符合REST标准的HTTP,但是请注意:RESTful HTTP并不是REST的全部,它只是利用了当前Web环境中通用的许多规范而已,例如使用URI来标识资源、使用HTTP来定义接口等


因此,只要我们能够拥有另一种通用的资源标识方式和通用的资源接口,我们就可以定义全新的REST架构。



REST的适用范围:


根据以上REST的特点可以看出,使用REST的关键是如何抽象资源,抽象得越精确,对REST的应用就越好。


如果我们可以把所有的用户需求都可以抽象为资源,那么就完全可以使用REST,而不必再使用MVC。


当然,这是非常理想的论断。可能我们无法找到一种方法可以把所有的用户需求都抽象为资源,这时混合使用REST和MVC也没关系。


但是对于希望利用REST的人来说,只要你开发的系统所设计的问题域可以被合理地抽象为资源,那么REST就会成为你的开发利器。