`
mybreeze77
  • 浏览: 3423 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

再谈RestAPI最佳实践

阅读更多

本文翻译自http://www.javacodegeeks.com/2014/05/rest-api-best-practices-reloaded.html ,仅供学习和参考,转载请注明出处。

 

近一年半,我参与了2到3个项目的工作,这些项目涉及到大量供“外部”使用的Rest API,稍后我们再来解释为什么要将“外部”这个词放在引号之中。在项目工作期间,我不得不对这些API进行反复地设计,再设计和重构,这篇文章是我对Rest API最佳实践的一些个人看法,希望读者能够从中获益。
 
更好、更早地设计
对于很多语言来说,实现Rest Service是一项极其微不足道的任务。换言之,无论你选择什么底层框架,只要辅以少量配置和代码,你可以在一小时之内就拥有一个Rest Service。虽然对于缺乏经验的人来说,这确实很方便,但它也很容易让你迅速写出一个质量低下的API。因此,在你编写代码之前,先留出一分钟的时间思考一下,试着去设计你的API,花足够的时间去理解业务范畴,判断客户端需要从你的系统中获取什么。举个例子,如果你的系统是针对一群硬币收藏家建立的数据库,此时你需要决定的是:你是否允许客户端添加新的硬币,或者仅仅允许取出原有的硬币;客户需要什么样的查询方式;如果遇上涉及大量数据检索的请求,你如何处理它?尽早地回答这些问题能够帮助你开发出更贴近用户需求的API。
 
名称与方法
现在已经很有多关于Resource命名和组织的讨论了,在这里我基于自己的经验再老调重弹一下,以下是三种应该遵循的规则。
1. 只使用名词:举个例子,如果你想提供一项在数据库中搜索硬币的服务,要避免将Endpoint命名为/searchCoins或/findCoins或/getAllCoins 等等,一个简单的/coins就已经足够了,当客户端发送一个GET请求的时候,可以获得所有有效硬币的集合。类似的,如果你想提供一项在数据库中添加硬币的服务,要避免使用诸如/addCoin或/saveCoin或/insertCointToDatabase这样的名称,你可以使用与上面相同的Rource名称,要改变的仅仅是用POST请求代替GET请求。同样地,对于更新硬币,可以使用PUT请求。

2. 如果需要获取单个硬币,又应该怎么做呢?我所建议的最佳方式是在Endpoint中加入一个参数,比如说客户端需要拿到一个ID是20的硬币,那么发送一个请求到/coins/20就足够了。我们再来看一个更复杂的例子,如果要让客户端能够为每个硬币添加一张图片,一个快速而丑陋的方式是/addCoinImage或/addNewImageToCoin等等。一个稍好一点的方式是/coins/addImage,但是正如我之前所说的,其中不应该有任何动词存在。还记得我们之前提到的获取某种硬币的方法吗?我们可以将其稍微加强一下,发送POST请求给/coins/20/images如何?目前看起来很不错。不过天下没有完美的事物,假设一下,如果我们要让一些超级用户能够从系统中删除硬币,根据我们之前的讨论,一个简单的DELETE请求发送给/coins/{id}就足够了,但是请你想一下,如果{id}仅仅是COINS表中的一个顺序编号,那会产生多大的问题?某人可以毫无压力地一个接一个的发送DELETE请求,最后系统中所有的数据全没了。我想说的重点是,使用标识符作为请求参数是不错,但是前提是这些标识符必须很难猜测或根本无法猜测。所以,如果你想要用一串序号去确定一个实体,那就忘了这种实现吧。我的建议是,不要使用Resource参数,直接发送一个DELETE请求给/coins,结合一个request body(比如json),其中拥有足够定位所要被删除的实体的参数,这就可以了。

3. 尽可能多的使用特定领域的名称。如果你的业务域中有一群硬币收藏家(Coin Collectors),那么当你设计API的时候,应当使用collectors这个词,而不是users或accounts。要避免使用一个意义过于宽泛的名称,这些名称不能代表什么,到了客户端又容易产生误解。对于请求参数的命名,道理也是一样的。另外,强烈建议给请求参数取一个尽可能短,同时又有意义的名称,举个例子,如果你想要查找在某一指定年份发行的硬币,一个很赞的参数名称是issueYear,比较典型的反例是:year(意义不明确),yearOfFirstIssue(包含无用信息)。
 
错误处理和响应
对于这个话题,我的经验是让客户端在每次发送请求后,都能获得相同格式的json响应,无论结果是成功还是失败,这将会给客户端处理带来极大的帮助。举个例子,你想要添加一个新的硬币,向/coins发送POST请求,一个成功的响应包含以下json文档:
 
{
     "meta":{
      "code":200
   },
   "data":{
      "coinId":"a7sad-123kk-223"
   }
}
 
一个错误的响应可能是这样的:
 
{
     "meta":{
      "code":60001,
      "error":"Can not add coin",
      "info":"Missing one ore more required fields"
   },
   "data":{
   }
}
 
请注意,对所有可能的结果(成功或失败),json响应的文档都具备相同的结构,其中有两种基本元素:meta和data,前者包含结果信息,在出错的情况下,其中还将包含一个特殊的error code,同时,"error"表示出错的内容,"info"表示出错的具体描述;后者(可选的)包含从服务器返回的所有数据,就拿上面的例子来说,当添加硬币成功后,服务器返回一个唯一的自动生成的标识符,如果有错误,这项就为空。这种做法的优势是,对于同一个API的各种服务类型和结果,客户端都可以采用相同的方式进行处理。此外,当有意外情况发生时,我们也可以传递一些额外的信息,正如上面例子中所展示的,"error"传达信息,"info"记录日志。还有一种选择,可以基于error code去处理响应,只要明确每个数字的含义即可,请记住这些数字并非http状态码,你依然要为每个请求返回正确的http状态码(如400、401等)。

在我们讨论下一节之前,我想强调另一个应该牢记的要事,假设我们不允许删除硬币,但是客户端尝试向/coins/{id}发送一个DELETE请求,通常情况下Web容器会返回一个405的状态码,但我发现,对这些响应进行过滤,返回相同的json文档,会很有帮助,比如我们可以返回:
 
{
     "meta":{
      "code":405,
      "error":"Method not allowed for the /coins/{id} resource",
      "info":"Method DELETE is not allowed for that resource. Available methods : GET, POST, OPTIONS"
   },
   "data":{
   }
}
 
这比原来好多了,不是吗?现在,响应内容不但包含原有的信息(405状态码),还通知客户端该Resource可用的方法。
 
文档
最后但也是最重要的一点,花一点时间,提供一份专业的、对开发人员友好的文档,并保证及时更新,一份过期文档的危害性比没有文档更甚。你可以使用一些开源免费的工具对你的API进行文档化。再好一点的做法是,对每一个Resource的使用方式都能提供范例,对成功或错误的响应能提供预期结果。不要忘了,在最后要记录下每一个error code并提供完整的信息,这样客户端才能在错误发生时做出反应,有一些客户端不会理会你的响应内容,它们会根据你的error code自行提供信息。
分享到:
评论

相关推荐

    ActiveMQ与REST API实践

    **ActiveMQ与REST API实践** ActiveMQ是Apache软件基金会开发的一款开源消息中间件,它遵循开放消息中间件标准——Java Message Service(JMS)。ActiveMQ以其高性能、稳定性和丰富的特性在分布式系统中广泛使用,...

    arcgis server rest api

    《ArcGIS Server REST API离线文档详解》 ArcGIS Server REST API是Esri公司提供的一种用于与ArcGIS Server交互的接口,它允许开发者通过HTTP/HTTPS协议访问和操作地理服务,进行地图数据的读取、写入以及处理。这...

    H3C CAS REST API接口

    正文: H3C CAS(Cloud Operating System)是华三通信公司推出的...在进行系统集成或二次开发时,务必确保遵循最佳实践,保证代码的安全性和可维护性,同时考虑到性能优化,以确保高效地利用H3C CAS提供的云基础设施。

    Python库 | plone.restapi-7.5.0.tar.gz

    标题中的“plone.restapi-7.5.0.tar.gz”是一个开源软件包,它基于Python编程语言,专为Plone内容管理系统设计。Plone是一个强大的、可定制的、基于Zope的应用服务器上的内容管理框架。这个包是plone.restapi的7.5.0...

    WordPress插件:给REST API 新增文章特色图片(缩略图)字段,用于显示文章头图

    - **RESTAPI**:理解RESTful概念和如何在WordPress中使用REST API是非常重要的,包括了解其结构、端点和数据格式。 通过创建这样一个插件,我们能够使REST API更好地服务于现代Web开发的需求,为那些依赖API获取...

    Building a Rest API with Spring

    本文主要介绍了使用Spring框架构建REST API的全过程,内容包括了从基础的Spring Web应用搭建,到使用Java配置,再到通过Spring Security进行安全认证和授权,以及REST API的其他重要特性,例如:使用HTTP消息转换器...

    asa-restapi-7131-lfbff-k8.SPA

    ASA restapi文件

    odoo rest api

    **Odoo REST API开发实践** 1. **模型操作**:通过REST API,你可以操作Odoo中的任何模型,例如创建新的销售订单、更新客户信息或删除产品记录。 2. **搜索和过滤**:利用查询参数,可以实现对数据的复杂查询,如按...

    restapi-version

    通过学习和实践这个"restapi-version"项目,开发者不仅可以掌握如何在Spring MVC中实现REST API版本控制,还能了解到如何在实际项目中处理版本升级带来的挑战。这有助于提高API设计的质量和稳定性,为未来的扩展和...

    Rest api下载

    根据提供的文件信息,本文将对“Rest api下载”这一主题进行深入探讨,并结合描述与链接内容,提炼出关键知识点。 ### 一、Rest API简介 REST(Representational State Transfer)是一种网络应用程序的设计风格和...

    Rest api服务器配置

    综上所述,配置Rest API服务器涉及多种技术和实践,从服务器环境的选择到API的设计和安全策略,都需要综合考虑。使用本软件包,你可以快速搭建并管理REST服务器,但理解上述概念和技术将有助于更好地利用这个工具。

    Python中的REST API调用:技术、工具与实践

    本文将详细介绍在Python中调用REST API的技术、工具及其实践应用。 调用REST API是Python网络编程中的一项基本技能。通过使用requests、http.client等库,可以轻松地发送HTTP请求、处理响应和错误。此外,通过高级...

    openshift-java-client, OpenShift REST API的Java客户端.zip

    openshift-java-client, OpenShift REST API的Java客户端 OpenShift客户端 OpenShift REST API的Java客户端。 它几乎提供了 rhc-* 命令行 工具( 。创建/重命名域,创建/销毁应用程序,列出应用程序,列出可用墨盒,...

    Learning WordPress REST API mobi

    Learning WordPress REST API 英文mobi 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    Activiti v7 REST API.postman_collection.json

    Activiti v7 REST API postman集合

    REST API.md

    REST是设计分布式网络服务或API时遵循的架构原则以及设计风格, 前后端分离最佳实践的开发标准或规范。本文为资料收藏的.md笔记,选取比较重要的资料,收集了以下内容: 重要概念介绍,如前述的第2-第4个关键词。 ...

Global site tag (gtag.js) - Google Analytics