REST真相

09-08-07 banq
              

REST不是CRUD, 本站已经进行大量讨论(见标签REST架构),那么REST到底是什么?

最严重的误解就是,将REST的POST, GET, PUT, DELETE和数据库资源的增删改查CRUD联系起来, POST, GET, PUT, DELETE = Create, Read, Update, Delete,这是相当多REST框架的错误导向。

从REST名词中,我们就看到状态的转移,也就是说,以URI为标志、以超文本或超媒体驱动(hypertext/Hypermedia)的状态转移是REST架构核心。真正REST API使用场景如下图。

1.一个简单的get就应该获得REST框架的入口点entry point,类似Atom Publishing Protocol的Discovery。如图中,返回的是一个Service列表,有的REST框架案例是在Service之前再做一个Action类,作为REST入口,其实没必要这么画蛇添足,直接将Service暴露给REST客户端,这才有SOA架势。

2.REST客户端会根据终端用户事件请求,定位某个Service,如果用户请求的是FooService,那么找到其入口点是/well=known-url/foo

3.客户端通过向/well=known-url/foo发出GET命令,获得FooService的列表List,如图中XML的fooitems,其中也包括下一步状态切换可能的URI:REVERSE,如果熟悉GOF设计模式的状态模式,就会非常自然理解这点。REST其实是把事件和状态分离到客户端和服务器两个部分。

4.如果终端用户发生请求事件,触发了状态转换,那么就激活fooitems中的REVERSE URI:/well=known-url/foo/1/reverse

5.注意了,这是区别于CRUD关键一步,这时客户端将向选择的下一个状态REVERSE URI发出PUT命令,服务器后端业务组件接受PUT命令后,将改变资源的状态。资源状态改变后返回一个操作结果。

6.客户端再次发出GET命令,获得当前服务器资源的状态。

CRUD vs. Hypermedia:

http://hinchcliffe.org/archive/2009/08/06/17119.aspx

Your Web Service Might Not Be RESTful If

你的Web服务也许不是RESTful

http://theamazingrando.com/blog/?p=107

RESTful架构深入分析

http://www.jdon.com/jivejdon/thread/36716.html

[该贴被banq于2009-08-07 11:32修改过]

[该贴被banq于2009-08-07 11:38修改过]


              

5
bloodrate
2009-08-07 16:23

问几个问题:

1、在上例中的状态转移,是不是指的

(1)空状态转移到服务列表状态

(2)服务列表状态转移到具体服务描述状态

(3)具体服务描述状态转移到操作结果状态

(4)操作结果状态转移到资源列表状态

2、这和传统的web模式有啥区别

(1)BookAction?method=getServices,返回包含所有services的HTML代码(相当于上文的xml),其中每个services是一个连接(相当于上文的URI)。

  (2)BookAction?method=servicesInfo&id=1,点击uri返回Service的信息HTML代码,包含提交请求的连接(相当于URI)

(3)附加提交信息调用BookAction?method=callservice&id=1,得到返回结果

我发现用传统struts就匹配上图模式,而且每一种资源都能匹配唯一uri,BookAction?method=getServices、BookAction?method=servicesInfo&id=1、BookAction?method=callservice&id=1,我的漏洞在哪?

banq
2009-08-07 16:47

BookAction?method=getServices是RPC,你调用参数中有服务的名称,而REST中如果要getService的话,调用/well=known-url/foo就可以了。

两者区别:

1. 可伸缩性,负载平衡,可以任意指定一个服务器上的服务,而且是由服务器这里指定的URI,可见我的"REST架构本质"一文。

2.调用/well=known-url/foo,客户端就不和具体服务名称耦合。

目前只想到这两点。

bloodrate
2009-08-07 17:11

>而且是由服务器这里指定的URI

我是不是可以这样理解,服务器初始化的时候为每个资源分配uri而不是拿服务的名字访问,比如说BookAction?method=getServices,有可能随着程序变更,这个服务不再需要了,但是用uri:/well=known-url/foo作为BookAction?method=getServices服务资源的访问uri,即便以后getServices不需要,也要其他的服务映射到/well=known-url/foo作为这个uri的资源,在这种假设下,产生两个疑问:

1 服务器在初始化的时候要知道全局的所有资源并为其分配uri,这其中是否涉及某种配置或者注册机制,而且依赖于分析人员前期对于资源的状态的准确定义

2 假如一张图片寸在于web项目的images目录下,为其分配uri为/well=known-url/images/1,但是开发人员应该用/well=known-url/images/1访问,却用http://localhost:8080/images/1.jpg访问,则这种非标准uri方式访问资源导致表述无法延续到下一个状态,将会导致致命错误。

banq
2009-08-07 17:14

>服务器初始化的时候为每个资源分配uri而不是拿服务的名字访问

可以这么理解。

其实SPring有个Web Flow,如果把它转移到客户端执行,就很有RESTful了。比如Web Flow中有:

<webflow id="LoginSequence" start-state="loginForm">

<action-state id="loginForm">

<action bean="loginFormAction"/>

<transition on="success" to="formView"/>

</action-state>

...

<view-state id="formView" view="enterCredentials">

<transition on="submit" to="bindAndValidateForm"/>

</view-state>

...

<end-state id="successView" view="displayMain"/>

还有工作流,都可以用REST来统一他们。

2Go 1 2 下一页