《你不知道的 JAVA》💘 什么是好的 Web Api 设计 (第一章)

第二章

Web Api 的重要性

设计 api 端点是后端开发经常接触的工作,但你是否从来没有想过好的 web api 应该是什么样子呢?

其实 Api 端点就像一张名片一样——专业的名片可以迅速帮助你与客户之间建立信任感;糟糕的名片会让你的产品在被使用前,就给客户留下负面印象。一旦客户对你的产品产生负面情绪,这种情绪就会蔓延到产品生态圈甚至于相关公司上。

本篇文章我和大家分享一些 api 设计的套路与规范,让你也能设计出优雅、健壮、扩展性强的应用程序接口。

设计原则,如果有的话

先让我们回顾曾经提到过的关于设计模式的内容:设计模式的精髓在于设计原则,而非模式的生搬硬套。与此类似,优雅的 Web Api 有两个重要原则如下所示:

  • 设计规范明确的内容必须遵守相关规范
  • 没有设计规范的内容必须遵守相关事实标准

也许你依然对如何设计 web api 毫无头绪,但是别着急,好的创作总是从模仿开始的。

下面是一些国际大厂的 api 示例,给自己一些时间消化消化。

厂名 uri 备注
Twitter api.twitter.com/1.1 “治国理政平台”
Google Calendar www.googleapis.com/calendar/v3 “大厂”
instagram api.instagram.com/v1/usrs/search?q=jack “宠物自拍网站”
linkedin api.linkedin.com/v1/people-search “招工”
Tumblr api.tumblr.com/v2 “真的不是成人网站”
foursquare api.foursquare.com/v2/venues/search?q=apple&categoryId=asad123456 “基于地理位置射交”

如何设计出国际范儿的 Api

背口诀

观察和分析上一小节中的国际大厂的设计往往都具备以下几个特点:

合理利用 REST API

REST API 的概念首先出现在 Roy Fielding 的论文中。

  • 狭义上的 REST API 实际上就是指符合 Fielding 的 REST 架构风格的 Web 服务系统。REST API 的设计风格严谨,考虑周全,结构优美。但过于苛刻的标准一直是狭义 REST API 推广壮大的绊脚石。
  • 广义上的 REST API 指符合 RPC 风格的 JSON + Http 的接口的系统。这样的 REST API 定义却又过于粗犷和随意了。

于是,针对 WEB API 的发展以及广义 REST 与 狭义 REST 的特点, Martin Fowler 提出在达到完美的 REST API 之前有以下几种 API 的设计级别。

  • REST LEVEL0: 使用 HTTP
  • REST LEVEL1: 引入资源的概念
  • REST LEVEL2: 引入 HTTP 动词
  • REST LEVEL3: 引入 HATEOAS 概念

按照 HTTP 协议中,URI 代表资源,而 HTTP method 代表对资源的操作。
我以此理论作为基础,再参照上述 REST LEVEL,设计了一个符合 REST LEVEL2 标准的示例 URI ,如下所示

目的 端点 方法
获取用户信息列表 api.example.com/v1/users GET
新用户注册 api.example.com/v1/users POST
获取特定用户信息 api.example.com/v1/users/:id GET
更新用户信息 api.example.com/v1/users/:id/ PUT/PATCH
删除用户信息 api.example.com/v1/users/:id DELETE

从今以后,你的 WEB API 只要参照以上示例,那就是符合基本标准看起来还不错的设计。

写在最后

  • 我是 Chuck1sn,一个长期致力于现代 Jvm 生态推广的开发者。
  • 您的回帖、点赞、收藏、就是我持续更新的动力。
  • 举手之劳的一键三连,对我来说是莫大的支持,非常感谢!
  • 关注我的账号,第一时间收到文章推送。

ps:本篇文章是通用概念,和 Java 关系不大。不过为了和我之前的 blog 关联在一起,我统一取了《你不知道的 Java》这个名字。如果需要查看之前的文章,请在论坛搜索关键词。

有问题欢迎在回复中留言,大家一起探讨。

85 个赞

太强了,大佬!

4 个赞

太强了,支持佬

4 个赞

哇,这波是狠狠的学习了
:tieba_087: 看了后发现我设计的是什么哇!一般都是直接拿业务起名笑死

4 个赞

感谢佬,学习起来 :grinning:

5 个赞

继续讲讲 rustful,想听

4 个赞

太强了!

5 个赞

大帅哥又来啦。

3 个赞

谢谢佬友的支持。后续还有各种文章要发,可以关注我的账号哈~

3 个赞

学习了。。。

3 个赞

感谢分享!

4 个赞

感谢分享

3 个赞

提问.如果某个查询需要用到非常复杂的参数如果按照REST的设计应该使用GET,但实际情况可能用params没办法表达该怎么办

3 个赞

REST 是可以用 params 的。刚好我下一章要讲查询的设计,可以关注我账号哈,方便收到推送。

这里提前说一下的话,就是你该用 GET+prams 的时候正常用,只要符合上面我提到了 REST LEVEL2 的设计就不算错,问题不大。

只是在端点命名的考虑上要稍微下点功夫,这个我下一章节继续讲。

2 个赞

不,我只的是类似es 那种超级复杂的查询…
es的早期做法是用GET + body.
这种方式我记得在rfc的定义中某些老的服务器会忽略body
而且很多http的库也不支持这种方式…
当然现在es是支持使用POST了.
但这明显与REST初衷违背了.

3 个赞

我明白你意思了,这种就只能特殊情况特殊处理了。不然 get 里面也放不下。

2 个赞

谢谢佬友支持。可以关注我哈,后面还有第二章,更新较多的干活。

3 个赞

谢谢佬友支持,阔以关注账号~

1 个赞

感谢分享,学习了

2 个赞

没问题,后续第二章会继续讲查询的设计。可以关注我的账号方便收到推送。

1 个赞