关于REST API设计的一些小经验

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://phoenixtoday.blogbus.com/logs/45855234.html

最近小组里有一些关于REST API设计的讨论,有些收获,打算在这里写一下。通常来讲设计第一个版本的REST API并不难,难点在于将来你要改变了这些API,而客户那里已经有对应的客户端实现, 那么你怎么保证兼容?或者,至少,你应当让这些东西失效吧,这样客户才能知道。所以基本上就是两个问题。

1,在最初设计时,如何尽量保证向后兼容?(这里不提倡过度设计噢,我们是搞敏捷的,哈哈)

2,如果API发生了改变,该怎么通知已有实现?

对于第一个问题,答案相对而言简单一些:支持必要的,但是最少的东西,而且层次不要太多。为什么?用下面的xml,举个例子来说



<person>

<name>phoenix</name>

<job>softerware developer</job>

<company>ThoughtWorks</company>

</person>



第一层,指的是这个xml具体针对什么,第二层有三个属性,分别是name,job和company,这是一个嵌套层次很好的,而且也没有包含过多的信息。但是如果我们在一开始再加上address属性(假设它并非必要),那么如果客户构建了一个客户端也的确包含了address属性,那么在下一个版本的API中,你把这个属性去掉了。问题是不是出现了?客户的软件无法工作了。反过来,如果最开始的版本不包含address,但是有客户强烈要求下一个版本要支持,那么怎么办?简单!在下一个版本加上就好了,对于已有的客户端,多一行冗余数据而已,也不会导致客户的软件无法工作。好了,这个问题解决了,那么,什么是嵌套层次不要太多。举个反例



<person>

<name>phoenix</name>

<job>softerware developer</job>

<company>

<name>ThoughtWorks</name>

<locations type="array">

<city>beijing</city>

<city>san francisco</city>

</locations>

<products>

<product>

<name>mingle</name>

</product>

<product>

<name>cruise</name>

</product>

<product>

<name>twist</name>

</product>

</products>

</company>

</person>



这叫层次太多!一个company里,包含了太多的嵌套信息,其中location还算说的过去(因为只是一个简单的数组),但是products里包含了子对象就不对了,这就是第三层对象了,具体的解决方案可以利用url来替换掉。世界终于清静啦!

可是我还不能清静,因为要回答第二个问题:API改变了,该怎么通知已有实现?这是一个很头疼的问题,如果能避免回答我绝对会避免,可惜,不能!通常有两种解决方案,但目的都是为了让客户的软件失效(我知道,我知道,这会让客户抓狂,可是我们也没辙啊!所以还是能不动,则不动,打死也不动,打不死嘛......就按如下办)a,使用带有版本号的API URL(这是现在最经常使用的一种方法),例如api/v2/projects/members.xml前面的api不说也明白,v2就是version 2版本2的意思,如果更换了,就变v3,客户的软件不能用了,也就知道了;b,利用HTTP header 里的ACCEPT来解决(别说你写了这么多年程序,连HTTP有HEAD都不知道啊!会被鄙视的!),ACCEPT可以设置接受的文件,你可以将版本信息放在里面。技术细节不多说了,给个链接,供大家参考 http://barelyenough.org/blog/2008/05/versioning-rest-web-services/ 其实我是比较赞成这种方式的,比较优雅,但缺点就是它还不是标准,对方的程序员也可能不知道HTTP有HEAD,所以做起来,对人家可能会有点复杂,这里就不再多说了。

总之昵~~,小初(想必盯我博客很久的人,也都知道我姓甚名谁了,以后我就用真名了)的技术博客在沉寂了,这么久之后,又回来了(我胡XX又回来啦!哈哈),有太多东西要写了,以后会陆续带给大家的,多谢捧场!

PS:为啥Blogbus不支持<pre>标签呢,让我的xml这么丑的出现在博客里?惭愧呀!

转载于:https://www.cnblogs.com/hnrainll/archive/2011/08/16/2140445.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/248389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1037 在霍格沃茨找零钱

题目传送门&#xff1a;https://pintia.cn/problem-sets/994805260223102976/problems/994805284923359232 题解&#xff1a; #include<iostream> using namespace std;int main() {int Galleon1, Sickle1, Knut1, Galleon2, Sickle2, Knut2;char c;cin >> Galleon…

我对创业和管理的一些看法

创业&#xff0c;对于刚工作的人&#xff0c;会比较兴奋&#xff0c;因为创业充满想象力&#xff1b;对于工作几年的人&#xff0c;会比较向往&#xff0c;因为压抑得太久。其实&#xff0c;创业和就业一样&#xff0c;只是实现自己人生价值的两种方式&#xff0c;关键是心态问…

关于Anaconda的环境和包管理

Anaconda相对于原生python解释器具有更好的包管理功能&#xff0c;它有一个env文件夹&#xff0c;里面包含所要管理的所有环境&#xff1b;日常操作时我们可能会使用pytorch、Tensorflow等多个环境&#xff0c;由于每个环境对Python的包的兼容性都不一样&#xff0c;所以我们可…

WCF basicHttpBinding之Message Security Mode

原创地址&#xff1a;http://www.cnblogs.com/jfzhu/p/4067873.html 转载请注明出处 前面的文章《WCF Security基本概念》介绍了WCF的security mode&#xff0c;简单说Transport是transport级别上的加密&am…

战略游戏

题目描述 Bob喜欢玩电脑游戏&#xff0c;特别是战略游戏。但是他经常无法找到快速玩过游戏的办法。现在他有个问题。 他要建立一个古城堡&#xff0c;城堡中的路形成一棵树。他要在这棵树的结点上放置最少数目的士兵&#xff0c;使得这些士兵能了望到所有的路。 注意&#xff0…

Vue语法学习第三课——计算属性

模板内的表达式非常便利&#xff0c;但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。对于任何复杂逻辑&#xff0c;都应当使用计算属性。 <div id"example"><p>original message : "{{message}}"</p&…

云计算学习资料分享:type查看命令

type 查看命令类型&#xff0c;例如该命令是alias&#xff0c;还是内置命令&#xff0c;还是某个文件&#xff0c;还是关键字 哪种神仙&#xff1a;天上还是地上&#xff0c;还是水里游的 [roottianyun ~]# type ll ll is aliased to ls -l --colorauto [roottianyun ~]# type …

neo4j删除所有节点

MATCH (n)OPTIONAL MATCH (n)-[r]-()DELETE n,r转载于:https://www.cnblogs.com/luoganttcc/p/10525189.html

Hadoop RPC实例

本文发表于本人博客。 上次写了个hadoop伪分布环境搭建的笔记了&#xff0c;今天来说下hadoop分布式构建的基础RPC&#xff0c;这个RPC在提交Job任务的时候底层就是创建了RPC来实现远程过程调用服务端。 我们首先可以通过Job的waitForCompletion(boolean verbose)方法来跟踪代码…

Django 模板语言 标签

前言&#xff1a;django的模板语法基本和flask的jinja2基本一样。下面比较一下两个模板语法的区别。 &#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;&#xff0d;深度变量的查找&#xff08;万能的句点号&#xff09; 在 Django 模板中遍历复杂数据结构的关键是…

电子书下载:Illustrated C# 2012 4th

下载&#xff1a;http://www.ctdisk.com/file/9015906转载于:https://www.cnblogs.com/MaxWoods/archive/2012/08/26/2657752.html

关于83版射雕英雄传

今天无意中看到网上一群人关于83版射雕的一些争论.或许一些现在的年轻人不喜欢83版射雕,说那太老土了,但想想那个时代的条件,能拍出这样的片子,是非常不错的,而且我觉得83版射雕也是最忠于原著的,跟后来的翻版比较,虽然从画面效果,人物服装方面存在差距,但这都是由于历史原因和…

ZOJ 3735 Josephina and RPG

思路&#xff1a;dp[i][j]:第i轮打完后&#xff0c;决定以j阵容打下一轮 保持原有阵容&#xff1a;dp[ i ][ j ] dp[ i - 1 ][ j ] * p [ j ][ s [ i ] ] 换成第i轮怪的阵容: for(int k0;k<r;k)dp[i][j]max(dp[i][j],dp[i-1][k]*p[k][s[i]]) 优化&#xff1a;用滚动数组&am…

4~20mA电流输出芯片XTR111完整电路(转)

源&#xff1a; 4~20mA电流输出芯片XTR111完整电路转载于:https://www.cnblogs.com/LittleTiger/p/10511115.html

电子书下载:Programming Microsoft LINQ in Microsoft .NET Framework 4

Book DescriptionDig into LINQ — and transform the way you work with data. With LINQ, you can query data from a variety of sources — including databases, objects, and XML files — directly from Microsoft Visual Basic or C#. Guided by data-access experts w…

原型模式 —— Java的赋值、浅克隆和深度克隆的区别

赋值 直接 &#xff0c;克隆 clone 假如说你想复制一个简单变量。很简单&#xff1a; int a 5; int b a; b 6;这样 a 5, b 6 不仅仅是int类型&#xff0c;其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。 但是如果你复制的是一个…

一个医院院长电视机坏了,拿到一个大修理店去修

一个医院院长电视机坏了&#xff0c;拿到一个大修理店去修。修理店接待人员:“OK&#xff0c;开机费50元”医院院长: “为什么还没修理就要先交费”&#xff1f;修理店接待人员: “我们修理店的制度就是这样&#xff0c;你们医院的挂号费&#xff0c;不是没看病之前就要交吗”&…

[scrum]2011/9/24-----第四天

scrum 总结&#xff1a; Team member Yesterday’s Work Today’s Work Issue R X Task201&#xff1a;Active Agenda Page的重写&#xff0c;界面设置 Task201&#xff1a;Active Agenda Page 界面的美化&#xff0c;收缩折叠&#xff0c;并添加一些动画效果 Task 243:…

c# 前后日期设置

List<string> list new List<string>(); //根据当月 显示前6个月 for(int i0;i<6;i) { list.add(DateTime.Now.AddMonths(i*-1).Tostring()); }转载于:https://www.cnblogs.com/Dcz1996/p/10515429.html

jq-AJAX 初步了解

js的异步操作(1) 定时器 (2) 事件 (3) 回调 (4) ajax Ajax优点 可以局部更新网页内容。 ajax的本质就是xmlHttpRequest对象控制台出现三个属性 readyState 请求的五个阶段 0 1 2 3 4 responseText 返回的文件内容 Status 状态吗 返回的状态信息 在__proto__有三个方法 …