锁定老帖子 主题:给Ajax技术初学者的一些建议
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2007-05-15
用rest和不用rest都能达到目的,但貌似leebai这种的
/cms/addColumn?fid=y&attr1=x1&attr2=x2... 像是在讲方言。 “post,Get,put,DELETE”的看上去就比较offical地表达 |
|
返回顶楼 | |
发表时间: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?这种多出一层的操作有现实意义吗? |
|
返回顶楼 | |
发表时间: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才叫简化? |
|
返回顶楼 | |
发表时间: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、其他意气之词,我就不反驳了。我到这里是来讨论问题,不是吵架,希望大家说话都客气点。世上没有绝对的真理,谁都有看走眼的时候,呵呵。 |
|
返回顶楼 | |
发表时间: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,还有什么别的语法? |
|
返回顶楼 | |
发表时间: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? |
|
返回顶楼 | |
发表时间: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处理所有服务请求一样。 |
|
返回顶楼 | |
发表时间:2007-05-15
感觉这个帖子应该封贴了。
这个问题或许有点仁者见仁,智着见智的味道。 都在兴头上,思想更容易走向极端。 既然都没有办法短时间说服对方,不如让时间去证明一切。 |
|
返回顶楼 | |
发表时间: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参数。当然很复杂的情况,也许需要增加点额外的判断。但是总体来说,需要增加的额外判断不多,也不会很复杂。 |
|
返回顶楼 | |
发表时间: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> |
|
返回顶楼 | |