您的位置:首页 > 其它

第二篇,REST风格介绍

2015-07-23 20:45 162 查看

REST简介

所谓REST(Representational State Transfer),其实只是一种软件架构风格。它只是一种设计风格,而不是一种协议。仅靠它本身是无法完成通讯的,它只是建议将所有的网络请求都转化成对资源的增删改查。这跟网络是一致的,网络本身就是一个资源的大集合,每天有许多新的资源产生(POST,增),有很多资源被阅读(GET,查),有很多资源被更新(PUT,改),又有很多资源过期被删除(DELETE,删)。哪怕是玩网络游戏,也可以归结到新增几件装备(POST),更新经验值和等级(PUT),查看自己的技能等级(GET),炼装备失败装备消息(DELETE)等等。。。如果说把接口以这样的方式设计出来,我们就说是符合REST风格的接口。现在百度开放平台很多接口都是号称以REST风格方式提供的,不过我怎么看都觉得不是那么像。

上面提到对资源的增删改查,又提到REST本身是无法完成通讯的,它只是接口的一种设计风格。在实际使用时,一般是基于HTTP协议的。HTTP的URL用来表示资源,HTTP的四个动词POST、DELETE、PUT、GET分别对应资源的增删改查。他们两者就是这么愉快的结合在一起。值得注意的是,GET和DELETE是不能带上请求数据的(URL的query部分除外),只有POST和PUT可以上传数据。

REST风格的接口设计

百度百科上关于REST有张图,我觉得很能具体说明该如何以REST风格设计接口,这张图分享给大家:



首先记住一点,REST风格必定是以资源为单位进行操作的。上图定义了(这段文字请对照上图阅读)对订单列表(orders)有GET和POST两种方式,相当于传统接口的GetOrderList和CreateNewOrder。由于不该开放出设置全部订单和删除全部订单的功能,因此PUT和DELETE未被使用。而对于单个订单(order)的操作,则是在orders后面跟上订单的id。接口对于单个订单的四种权限全部开放,相当于是QueryOrderDetail(查询订单详情), UpdateOrderDetail(更新订单详情,比如选择了优惠方式),
AddItemInOrder(新增订单内的物品,比如多购买了一件物品),CancelOrder(取消订单)。后面关于顾客的操作也是如此,这样整套接口就是完全符合REST风格的。

然而至少到目前为止,并没有人能证明,所有的功能都能等价转换成对资源的操作。因此,想要完全符合REST风格去设计接口,有一定的难度。但是不得不说,符合REST风格的接口确实很让人赏心悦目。这里需要补充说明一点:符合REST风格定义的接口所表示的资源都有4种操作(无论是否合理、有效),这4种操作必须分别设计成如下形式:

GET,对资源的请求。无论请求多少次,都不能对资源本身产生任何影响。这里用不专业的话,表述了什么叫幂等性。

PUT,对资源进行更新,将资源的某些属性设成特定的值。这个接口是“安全”的。

DELETE,对资源进行删除。接口必须能处理对已经删除的资源“再次删除”,也要能处理对“不存在的资源的删除”。这样这个接口也是“安全”的。

特别的,POST,新增资源。这个接口既不安全,也不幂等。需要特别而专门的处理。这里定义的“安全”是指可以重复调用,而不会引起任何副作用。因为在网络请求中,你永远无法确定,你是发出的包根本没有到达服务器,还是服务器处理后回复的包没有被你接收到。只有幂等或安全的接口,我们才可以在没有收到服务器回复时义无反顾的重发。简单的办法,是为POST请求增加一个序号或时间戳,这样服务器就能根据序号或时间戳判断是否是重发的请求,从而使接口变成“安全”的。

资源的表示

还记得初中时,有一门课上老师讲到,信息(Message)是看不见、摸不着的,我们能看见的只是信息的表示。资源也算是一种信息吧?或者信息是资源的一种?这种绕的逻辑,我们就不研究了。但是在REST里,资源确实被定义成不可见的,可见的是资源的表示(Represention)。而资源的表示有很多方式,比如一首歌曲,可以用mp3格式的音频来表示,可以用简谱来表示,也可以用五线谱来表示,等等。而用在接口上,我们用来表示资源最多的就是json和xml。其中xml由于较费流量,略逊json一筹。现在大概最流行的方式就是通过Jackson将JavaBean与json或xml互转了吧。这样写接口的时候,定义好请求的类,定义好回复的类,请求时“扔出”一个对象,收到服务器的回复也是一个“对象”,完全屏蔽了中间序列化和反序列化的过程。

较为优秀的REST框架实现

Jersey和Restlet是目前两个比较好的实现,其中Restlet支持的平台较广,Android也有支持,而Jersey没有。但是不建议在Android端使用Restlet,因为Restlet的实现大概有1.5M,对于移动端这种需要控制安装包大小的场景不适合。坦白说,REST的实现非常简单,在Android上使用Apache的HttpClient或者Android推荐的HTTPUrlConnection都可以。只需要三步(以json表示资源为例):

1、选择一个json的序列化和反序列化工具,如jackson、gson、flexjson等。推荐使用gson,因为它的jar包大小适中,约为160K,性能稳定。虽然在少量数据的处理效率上不如flexjson,但大量数据的处理,gson占很大优势。jackson其实是一个很好的jar包,可惜就是太大了,用在服务器上比较合适。flexjson大约只有80K,少量数据的处理效率十分出色,而且api风格十分优美,唯二不足的就是:a、新手不注意看文档,序列化方法有两个,一个带deep,一个不带deep,选了不带deep的就坑了。。b、byte[]居然是一个byte一个byte的转成10进制输出,中间用逗号隔开。。大量的流量就没了。。好在也有解决办法,只需将这个字段设成String(服务器端如用jackson解析,仍可保持byte[]不变),在设值的时候,自己调用Base64.encodeToString转换。上一篇博客当中,我说过的,json和xml是文本标记语言,是不能存储字节数组的。而传输字节数组,目前最好的办法就是Base64编码和解码。

2、在HTTP的Header中加入:Content-Type: application/json

3、如有请求的数据,在HTTP请求的BODY中直接设置。

至此,关于REST的介绍应该算是比较完整了。关于HTTP协议相信很多人都有所了解,但为了照顾一些初学者,或者还没有接触到过的人,我会在我后面的博客中介绍。初写博客,如果我写的内容对你有所帮助,请留言鼓励一下;如有错误之处,恳请大神指正,谢谢!~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: