论坛首页 Web前端技术论坛

给Ajax技术初学者的一些建议

浏览 65404 次
该帖已经被评为精华帖
作者 正文
   发表时间:2007-05-15  
用rest和不用rest都能达到目的,但貌似leebai这种的

/cms/addColumn?fid=y&attr1=x1&attr2=x2...


像是在讲方言。

“post,Get,put,DELETE”的看上去就比较offical地表达
0 请登录后投票
   发表时间:2007-05-15  
robbin 写道
协议         URI                                   解释
----------------------------------------------------------------------
POST       /columns                         新建栏目
DELETE     /columns/1/subcolumns/1          删除某栏目下面的某子栏目
DELETE     /columns/1/subcolumns            删除某栏目下面的某些子栏目
DELETE     /columns/1                       删除某栏目及其所有子栏目
PUT        /columns/1                       修改某栏目属性
GET        /columns                         取所有栏目
GET        /columns/1/subcolumns            取某栏目的所有子栏目
PUT        /columns/1/subcolumns/1          发布某栏目的某子栏目
PUT        /columns/1/subcolumns/1          撤销某栏目的某子栏目
PUT        /columns/1/subcolumns/1          移动子栏目
PUT        /columns/1                       合并栏目,移动栏目,......
PUT        /columns/1/subcolumns            批量修改子栏目的显示顺序


REST到不是说URI不能带CGI参数,其实也可以带CGI参数的,REST的核心在于定义资源+操作。凡是针对GET请求的request参数完全可以以?name=value方式传递,其他协议的参数不是在URI后面带的,是数据提交POST里面带的,不需要在URI上面标出来。




ok,不错,但是。。。

1、这种写法必须加上URL参数,才与我的写法语义等价:

1、新建栏目(fid是父栏目ID) 

addColumn?fid=y&attr1=x1&attr2=x2...
POST /columns?fid=y&attr1=x1&attr2=x2...


2、删除某栏目下的N个子栏目 

deleteColumn?id=y1&id=y2...
DELETE /columns/1/subcolumns?id=y1&id=y2... (我不知道选中的N个资源的操作你怎么表达?资源id放到URL参数里好象不是REST的风格?) 


3、删除某栏目,连带其所有子孙栏目 

deleteColumnWithSub?id=y
DELETE /columns/1    


4、修改栏目属性 

updateColumn?id=y&attr1=x1&attr2=x2...
PUT /columns/1?&attr1=x1&attr2=x2...


5、取整个栏目树(某些UI界面需要列出所有的栏目) 

/getAllColumn
GET /columns


6、取某个栏目下的所有子栏目(管理界面的栏目树要动态加载子栏目节点) 

/getSubColumn?id=y
GET /columns/1/subcolumns


7、发布某个子栏目(对CMS,只有发布的栏目才可访问) 

/cms/publishColumn?id=y
PUT /columns/1/subcolumns/1?action=publish   (复合谓语出来了,好看吗?后台程序好写吗?)


8、撤消某个子栏目(反发布) 

/cms/disPublishColumn?id=y
PUT /columns/1/subcolumns/1?action=dispublish  (同上)


9、将子栏目y从父栏目A1移动到父栏目A2 

/cms/moveColumn?id=y&tfid=A2
PUT /columns/1/subcolumns/1?action=move&&tfid=A2 (这可以称之为最丑陋的Request了,复合谓语+资源ID不在URI中,不伦不类)


10、将栏目y与栏目A合并 
/cms/mergeColumn?id=y&tid=A
PUT /columns/1  (我就不知道该怎么补了,呵呵,估计全写出来也是吓死人)


11、将栏目在兄弟栏目中的位置上移一位 
/cms/moveColumnUp?id=y
PUT /columns/1  (同上)

12、将栏目在兄弟栏目中的位置下移一位 
/cms/moveColumnDown?id=y
PUT /columns/1  (同上)

13、将栏目在兄弟栏目中的位置移到顶部 
/cms/moveColumnTop?id=y
PUT /columns/1  (同上)

14、将栏目在兄弟栏目中的位置移到底部 
/cms/moveColumnBottom?id=y
PUT /columns/1  (同上)

15、批量改变某栏目下所有子栏目的显示顺序(11-14功能的另一种实现方式) 
/cms/reorderSubColumns?id=y1&order=x1&id=y2&order=x2...
PUT /columns/1/subcolumns?action=reorder&id=y1&order=x1&id=y2&order=x2... (同9)


2、这样写的好处在哪?后端编程简单了?还是代码容易维护了?还扩展性好了?还是设计好看?

3、对于操作牵涉N个资源的情况,以及出现复合谓语的情况,REST风格描述够难看的了吧?

4、栏目y与栏目A合并,本来对等的资源,为什么写起来一个是URI,一个是参数?,如果N个资源的互相操作呢?这种抽象服务器端开发是简单化吗?

5、对于功能复杂的资源,如果大部分操作功能只能用put+辅助谓词表达,这时就REST就退化为和POST没有区别,为什么不干脆全用POST?这种多出一层的操作有现实意义吗?

0 请登录后投票
   发表时间:2007-05-15  
关于REST有好几个地方,其实你都没有理解,我想还是你自己去下功夫钻研一下比较好。

引用
这种写法必须加上URL参数,才与我的写法语义等价......


你似乎认为传递参数只能通过URL后面的?name=value,那我不得不说你应该好好看一看HTTP协议的规范。

引用


1、新建栏目(fid是父栏目ID)   
addColumn?fid=y&attr1=x1&attr2=x2...  
POST /columns?fid=y&attr1=x1&attr2=x2...


POST/PUT操作都不需要通过URL方式传递参数。参数和数据是封装在POST/PUT提交的body部分的。这是HTTP的基础知识了。即使不用REST,如果你的页面弄出来像上面的URL,说明你对web编程还没有入门呢。

引用
2、这样写的好处在哪?后端编程简单了?还是代码容易维护了?还扩展性好了?还是设计好看?

你说SQL有什么好处?简单易用,这就是REST的好处。唯一确定的URI资源加上四种基本操作就足够表达对web应用的外观了。

引用
3、对于操作牵涉N个资源的情况,以及出现复合谓语的情况,REST风格描述够难看的了吧?

资源之间可以嵌套,你上面也看到了,对于同一类型的资源,完全没有必要搞什么复合谓语,他就是个 PUT URI,针对某项资源的修改操作而已。不是REST难看,是你自己臆测的描述难看。

引用
4、栏目y与栏目A合并,本来对等的资源,为什么写起来一个是URI,一个是参数?,如果N个资源的互相操作呢?这种抽象服务器端开发是简单化吗?

把栏目y合并到栏目A里面去,本质上就是对栏目A这个资源的修改操作,n个资源也是一回事,归根结底就是对n项资源(或者对某些资源集合)的操作。 怎么不简化阿? 资源加上4种操作,就这么点东西,还不简化?难道你那种带一大堆参数的URL才叫简化?











0 请登录后投票
   发表时间:2007-05-15  
robbin 写道
引用
HTTP协议最初的设计本意是针对HTML/GIF/JPG等无结构的简单Web资源的增删改查,再加上缓存机制。GET/POST/PUT/DELETE(还有OPTIONS/HEAD/TRACE/CONNECT)等谓语动词对那些无结构的简单Web资源以及对这些资源所须的简单操作是匹配的,合适的。

但是现实系统的操作谓语何止千万,现实系统的资源结构是何等复杂,岂是这区区G/P/P/D四种元操作所能表达,如果硬要套用G/P/P/D,只能让服务操作演变成两层操作定义(或叫复合谓语):第一层是G/P/P/D,第二层再分Action,这样把简单问题复杂化。


说到底,你还是不相信GET/POST/PUT/DELETE四种语义是完备的。这四种语义的完备性是REST理论的基础,要想证伪它的话,就要看你能不能提出有力的证据了。


引用
其次,这种以URI为中心的模式,和面向对象语法一样,也有一个天然缺陷:对N个资源做同一种操作时很别扭,只能利用谓语优先逻辑。其实HTTP协议的本意也是谓语优先的,面向过程的。但是Fielding同志抓住URI不放,生硬地将其理解成面向对象的,这就是REST的由来。


没听说REST和面向对象有什么关系,这完全是你自己在臆测了,REST的理论基础是资源+操作,而面向对象的理论基础是消息传递,完全两码事。

当然Fielding同志的主观出发点是好的,是想充分利用HTTP协议的cache机制、无状态机制来解决Web应用的性能问题和服务器集群问题;但后来Fielding将REST无限上纲,将本来被当代Web应用彻底废弃的put/delete等覆满灰尘的东西都搬出来,想学SQL语言用四种基本操作来映射世间万物,想用四座大山、四项基本原则来约束广大开发者的思想自由,这就很不应该了。须知SQL的select/insert/update/delete都是原子操作,只对单表,单数据类型;而现实的Ajax请求基本上都是事务操作,在SQL中的对应物是存储过程,如果Web服务请求可以概括为CURD,那么存储过程的设计者脑子就有问题了。

SQL也是同一个道理,针对资源(数据库表)的四种操作。恐怕不是存储过程设计者脑子有问题。是你的脑子太僵化了。


1、我从来不怀疑CRUD的语义完备性,但那只是原子操作层面,而ajax请求是HTTP请求,每个请求必须是一个事务操作,里面很多情况下会包含一组原子操作,这两者是不同粒度的操作。你如果只用四种原子操作去概括所有事务操作,必然要引入辅助谓词,也就是除了PUT,你还要用另外一个动词指明是什么PUT,这种设计其实是很拙劣的。REST的特点就是简单的问题处理得很漂亮,复杂的问题越摸越黑。

2、一个系统对外提供什么服务,是有操作粒度约束的,不是因为CRUD的语义完备,就可以只用CRUD。理论上说SQL的select/insert/update/delete和CRUD一样语义完备,但SQL语句却远不止这四个,大家想一想为什么。

3、其他意气之词,我就不反驳了。我到这里是来讨论问题,不是吵架,希望大家说话都客气点。世上没有绝对的真理,谁都有看走眼的时候,呵呵。
0 请登录后投票
   发表时间:2007-05-15  
引用

1、我从来不怀疑CRUD的语义完备性,但那只是原子操作层面,而ajax请求是HTTP请求,每个请求必须是一个事务操作,里面很多情况下会包含一组原子操作,这两者是不同粒度的操作。你如果只用四种原子操作去概括所有事务操作,必然要引入辅助谓词,也就是除了PUT,你还要用另外一个动词指明是什么PUT,这种设计其实是很拙劣的。REST的特点就是简单的问题处理得很漂亮,复杂的问题越摸越黑。


不要说对REST了解了,就是对HTTP协议的基础知识你现在都还有错误的认识,这就贸然下了结论说REST拙劣了? 那我可真没啥兴趣再和你讨论下去了。


引用
2、一个系统对外提供什么服务,是有操作粒度约束的,不是因为CRUD的语义完备,就可以只用CRUD。理论上说SQL的select/insert/update/delete和CRUD一样语义完备,但SQL语句却远不止这四个,大家想一想为什么。


恕我孤陋寡闻,标准SQL92的DML除了select/insert/update/delete,还有什么别的语法?
0 请登录后投票
   发表时间:2007-05-15  
robbin 写道

你似乎认为传递参数只能通过URL后面的?name=value,那我不得不说你应该好好看一看HTTP协议的规范。

POST/PUT操作都不需要通过URL方式传递参数。参数和数据是封装在POST/PUT提交的body部分的。这是HTTP的基础知识了。即使不用REST,如果你的页面弄出来像上面的URL,说明你对web编程还没有入门呢。

资源之间可以嵌套,你上面也看到了,对于同一类型的资源,完全没有必要搞什么复合谓语,他就是个 PUT URI,针对某项资源的修改操作而已。不是REST难看,是你自己臆测的描述难看。



robbin老弟...睁大眼睛...看看我的原贴:
---------------------------------------
.....我已经用URL参数方式表达(这里只是表达功能,现实中我只用表单POST提交),。。。
----------------------------------------
之所以要写成完整URL,就是为了在“等价语义”的情况下进行对比。

偶写程序21年,写Web程序也有8年了,第一次被认为“web编程还没有入门”,呜呜。。。。


robbin 写道

引用
4、栏目y与栏目A合并,本来对等的资源,为什么写起来一个是URI,一个是参数?,如果N个资源的互相操作呢?这种抽象服务器端开发是简单化吗?

把栏目y合并到栏目A里面去,本质上就是对栏目A这个资源的修改操作,n个资源也是一回事,归根结底就是对n项资源(或者对某些资源集合)的操作。 怎么不简化阿? 资源加上4种操作,就这么点东西,还不简化?难道你那种带一大堆参数的URL才叫简化??


一大堆参数的URL都是为了"等价语义",ok?

上面我说了对于复杂资源,有N多的操作,其中大部分操作只能共用一个PUT操作,这时REST唯一的稻草就是在请求中加一个Action参数来表示到底要干什么。这绝对不是REST的优美之处,yes?










0 请登录后投票
   发表时间:2007-05-15  
robbin 写道
引用

1、我从来不怀疑CRUD的语义完备性,但那只是原子操作层面,而ajax请求是HTTP请求,每个请求必须是一个事务操作,里面很多情况下会包含一组原子操作,这两者是不同粒度的操作。你如果只用四种原子操作去概括所有事务操作,必然要引入辅助谓词,也就是除了PUT,你还要用另外一个动词指明是什么PUT,这种设计其实是很拙劣的。REST的特点就是简单的问题处理得很漂亮,复杂的问题越摸越黑。


不要说对REST了解了,就是对HTTP协议的基础知识你现在都还有错误的认识,这就贸然下了结论说REST拙劣了? 那我可真没啥兴趣再和你讨论下去了。


引用
2、一个系统对外提供什么服务,是有操作粒度约束的,不是因为CRUD的语义完备,就可以只用CRUD。理论上说SQL的select/insert/update/delete和CRUD一样语义完备,但SQL语句却远不止这四个,大家想一想为什么。


恕我孤陋寡闻,标准SQL92的DML除了select/insert/update/delete,还有什么别的语法?


wait...

DML: FETCH,COPY_TO

即使DML只有select/insert/update/delete,想过没有:为什么还要DDL,从语义完备性上说,理论上select/insert/update/delete也能做DDL要做的那些事的?  唯一的解释是:那样做不优美,就像用REST处理所有服务请求一样。
0 请登录后投票
   发表时间:2007-05-15  
感觉这个帖子应该封贴了。

这个问题或许有点仁者见仁,智着见智的味道。
都在兴头上,思想更容易走向极端。

既然都没有办法短时间说服对方,不如让时间去证明一切。
0 请登录后投票
   发表时间:2007-05-15  
引用
上面我说了对于复杂资源,有N多的操作,其中大部分操作只能共用一个PUT操作,这时REST唯一的稻草就是在请求中加一个Action参数来表示到底要干什么。这绝对不是REST的优美之处,yes?


嗯,我明白了你的意思。但是你这个担心很可能是多余的。例如

PUT /columns/1/subcolumns/1

定义了对某子栏目的修改操作,但是修改可能包括了:修改子栏目名称,发布子栏目,撤除子栏目。

按照你的理解,需要通过传递参数来标示不同的操作类型,例如:

_action=modify
_action=publish
_action=remove

这是典型的Java Struts编程思维,我记得在n年前,我为了合并同类型操作,就需要在页面里面放入隐藏域标示操作类型,以便在action代码里面根据类型做相应操作。

但是RoR很可能不需要:
如果是修改子栏目,那么页面表单提交会包含 [subcolumn][name]="xxx"      这样的信息
如果是发布子栏目,那么页面表单提交会包含 [subcolumn][publish]="true"  这样的信息
如果是修改子栏目,那么页面表单提交会包含 [subcolumn][publish]="false" 这样的信息

最终PUT对应的都是同一个方法:

def update 
  subcolumn = SubColumn.find_by ....
  subcolumn.update_attributes(params[:subcolumn])
end


不管你是干嘛的,我就是这么一条语句搞定,根本不需要什么action参数。

通过POST/PUT的body携带的参数,已经可以很清楚的表明,要做的是什么事情了。实践上不需要什么action参数。当然很复杂的情况,也许需要增加点额外的判断。但是总体来说,需要增加的额外判断不多,也不会很复杂。



0 请登录后投票
   发表时间:2007-05-15  
我是不大敢和坛主交锋的 

robbin肯定是有一些实践体会的 dlee也是所以很自信。其实他们谈的我不仅明白还做过。

但是那 直接用post一样能实现rest 而且不仅仅局限于rest 我想这个dlee没有尝试过 否则不会一再误会我的意思。

我只所以觉得post更出色 是因为有些应用根本就不是面向资源的 只是要返回加工后的结果 当然用rest的方式也不是不可以 但是很别扭。

谈到这里就不得不说说SOA 。也就是组合web servic的问题。

有时候信息服务并非是对某个资源的访问。 比如我现在要获得所有连锁俱乐部的服务价格清单 并用execel输出 然后email给apple. 在ajax中这是一步操作 只需返回ok

如果用rest去实现它 。。。。 这个留给rest狂热分子去思考吧虽然我也有办法

现在我用post去实现它

1 价格清单聚合 服务
2 xslt转换excel 服务
3 email server 服务

ajax 根据用户的交互 向post数据提交三个动作和相关参数
<post>
<acts>
<act>
<name>价格清单聚合</name>
<参数/〉
<act>
<act>
<name>xml->excel转换</name>
<act>
<act>
<name>mail服务</name>
<参数/〉
<act>
<acts>
</post>






0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics