GraphQL 是Facebook于 2012 年在内部开发的数据查询语言,在 2015 年开源,旨在提供RESTful架构体系的替代方案。

GraphQL和RESTful一样,都是一种网站架构,一种前后端通信规范,不涉及语言,不同语言有不同的实现方案。

GraphQL目前被认为是革命性的API工具,因为它可以让客户端在请求中指定希望得到的数据,而不像传统的RESTful那样只能呆板地在服务端进行预定义。

这样它就让前、后端团队的协作变得比以往更加的通畅,从而能够让组织更好地运作。

而实际上,GraphQL与RESTful都是基于HTTP进行数据的请求与接收,而且GraphQL也内置了很多RESTful模型的元素在里面。

那么在技术层面上,GraphQL和RESTful这两种API模型到底有什么异同呢?我的观点是,他们归根到底其实没多大区别,只不过GraphQL做了一些小改进,使得开发体验产生了较大的改变。

我会从API的各个组件分别来讨论GraphQL和RESTful都分别是如何处理的。

RESTful的核心思想就是资源,每个资源都能用一个URL来表示,你能通过一个GET请求访问该URL从而获取该资源。

根据当今大多数API的定义,你得到一份JSON格式的数据响应,整个过程大概是这样:

复制
GET /books/1
{
“title”: “Black Hole Blues”,
“author”: {
“firstName”: “Janna”,
“lastName”: “Levin”
}
// … more fields here
}
注:上面的例子里的"author"也会作为一个单独的资源在其他RESTful API中被用到

需要注意的是,在RESTful中,一个资源的种类与你获取它的方式是耦合的。比如上面这个例子中的API就可以称之为“book端点”(book endpoint)。

在这一点上GraphQL就大为不同,因为在GraphQL里这两个概念是完全分离的。比如在你的schema定义中,你可能会有Book和Author两个类型(type):

type Book {
id: ID
title: String
published: Date
price: String
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
books: [Book]
}
注意这里我们虽然定义了数据类型,但却不知道该如何获取这些数据。

这是RESTful与GraphQL的一个核心差异:资源的描述信息与其获取方式相分离。

如果要去访问某个特定的book或者author资源,后端需要在schema中创建一个Query类型:

type Query {
book(id: ID!): Book
author(id: ID!): Author
}
然后,前端就可以像RESTful那样发送请求了:

GET /graphql?query={ book(id: “1”) { title, author { firstName } } }
{
“title”: “Black Hole Blues”,
“author”: {
“firstName”: “Janna”,
}
}
虽然都是通过请求某个URL来得到相同的响应,但这里我们已经看到GraphQL与RESTful的差异之处了。

首先,我们看到GraphQL的URL请求里面指定了我们所需要的资源以及在该资源中我们所关心的字段。

另外,我们是主动请求得到与book相关的author数据的,而不是服务端替我们决定的。

最重要的是,在请求中我们不需要关心资源的主键和资源之间的关系定义,我们可以通过除id以外的其他字段来获取到相同的Book资源。

小结
现在我们知道的异同点有:
相同点:

都有资源这个概念,而且都能通过ID去获取资源
都可以通过HTTP GET方式来获取资源
都可以使用JSON作为响应格式
差异点:

在RESTful中,你所访问的路径就是该资源的唯一标识(ID);在GraphQL中,该标识与访问方式并不相关
在RESTful中,资源的返回结构与返回数量是由服务端决定;在GraphQL,服务端只负责定义哪些资源是可用的,由客户端自己决定需要得到什么资源
如果你已经用过GraphQL和RESTful,以上这些对你来说肯定相当简单。如果你之前没有用过GraphQL,你可以在到这里来实际体验一下。

回到顶部
路由(URL Route) vs GraphQL Schema
一个具有可预见性的API才是好的API。

因为你通常会把一个API当做程序的一部分来使用,所以你必须要知道它需要接收什么参数并预期能够获取到什么样的结果。

这时候,对API的访问描述信息就显得很重要。通常我们会通过阅读API文档来获取信息,但通过GraphQL的Introspection机制、以及Swagger这样的RESTful API工具,这些信息就能可以自动获取到。

如今的RESTful API通常会由一系列的URL端点组成:

GET /books/:id
GET /authors/:id
GET /books/:id/comments
POST /books/:id/comments
你可以把这种API的形态称之为线性结构——因为这就是一个列表嘛。

当你要获取数据时,第一个事情就是搞清楚你要访问的是哪个端点。

而在GraphQL中——其实在上一节里你也看到了——可以通过查看GraphQL schema获得相关信息:

type Query {
book(id: ID!): Book
author(id: ID!): Author
}
type Mutation {
addComment(input: AddCommentInput): Comment
}
type Book { … }
type Author { … }
type Comment { … }
input AddCommentInput { … }
RESTful会使用类似GET、POST这样的动词去请求相同的URL来表示这到底是一个读操作还是写操作,而GraphQL会使用不同的预定义类型:Mutation和Query。

在GraphQL请求中,你可以通过不同的关键字进行不同的操作:

query { … }
mutation { … }
如果你想知道更多关于query的用法,请看我之前写的文章“The Anatomy of a GraphQL Query”

这里的Query类型定义与上面的RESTful路由是完全契合的,同样表示了数据的访问入口,因此这是GraphQL中最能与RESTful的URL端点所对应的概念。

如果是对资源的简单查询,GraphQL与RESTful是类似的,都是通过指定资源的名称以及相关参数来取得,但不同的是,在GraphQL中,你可以根据资源之间的关联关系来发起一个复杂请求,而在RESTful中你只能定义一些特殊的URL参数来获取到特殊的响应,或者是通过发起多个请求、再自行把响应得到的数据进行组装才行。

小结
RESTful对数据的描述形式是一连串的URL端点,而GraphQL则是由相互之间有所关联的schema组成。
相同点:

RESTful API的URL端点列表与GraphQL的Query/Mutation中的字段类似,都表示数据的访问入口
都能用不同的方式描述一个API请求到底是读操作还是写操作
差异点:

GraphQL让你可以通过一个资源入口访问到关联的其他资源,只要事先在schema中定义好资源之间的关系即可;而RESTful则提供了多个URL端点来获取相关的资源
在GraphQL中,Query类型可以在一个请求的根节点中被访问,除此以外它跟其他类型没有区别,比如你也可以对一个query中的字段添加参数。而在RESTful中,即使响应结果是嵌套关系,但在请求中并没有嵌套的概念
RESTful使用POST这样的HTTP方法名称来定义写操作,GraphQL则是查询结构中的关键字
正因为上述的第一个点,人们通常会把Query类型中的字段称为GraphQL中的“端点”或“查询条件”。

虽然这是一个合理的解释,但同时也会对其他人造成误导,让人以为Query类型是一个非常特殊的类型。

回到顶部
路由处理器(Route Handlers)vs 解析器(Resolvers)
想象一下,当你调用一个API的时候,实际上会发生什么事情?

应该是在服务器上面执行了一些代码来处理这个请求,可能是进行了一些计算,可能从数据库中加载了一些数据,也可能是再次调用了一个别的API。

虽然总的来说,作为调用方你并不需要知道内部发生了什么事情,不过由于RESTful和GraphQL都提供了标准的API实现方法,我们可以通过对比来感受一下两者之间的差异。

因为我比较熟悉JavaScript语言,所以在这个章节中我会使用它来做例子,但你也可以使用其他主流编程语言来实现RESTful或者GraphQL的API。为了突出重点,我会忽略掉一些构建服务用的过程代码。

首先使用Express实现一个hello world:

app.get(‘/hello’, function (req, res) {
res.send(‘Hello World!’)
})
这里我们得到了一个可以返回“Hello World!”这个字符串的/hello端点。从这个例子我们可以看到一个RESTful API请求的的生命周期:

服务器收到请求并提取出HTTP方法名(比如这里就是GET方法)与URL路径
API框架找到提前注册好的、请求路径与请求方法都匹配的代码
该段代码被执行,并得到相应结果
API框架对结果进行序列化,添加上适当的状态码与响应头后,返回给客户端
GraphQL差不多也是这样工作的,我们来看下这个对应的hello world例子:

const resolvers = {
Query: {
hello: () => {
return ‘Hello world!’;
},
},
};
我们看到,这里并没有针对某个URL路径提供函数,而是把Query类型中的hello字段映射到一个函数上了。

在GraphQL中这样的函数我们称之为解析器(Resolver)。

然后我们就可以这样发起一个查询:

query {
hello
}
至此,总结一下服务器对一个GraphQL请求的执行过程:

服务器收到HTTP请求,取出其中的GraphQL查询
遍历查询语句,调用里面每个字段所对应的Resolver。在这个例子里,只有Query这个类型中的一个字段hello
Resolver函数被执行并返回相应结果
GraphQL框架把结果根据查询语句的要求进行组装
因此我们将会得到如下响应:

{ “hello”: “Hello, world!” }
这里有个小技巧:我们其实可以多次调用同一个Resolver:

query {
hello
secondHello: hello
}
在这个例子中的生命周期跟上面的是类似的,但因为我们通过别名来两次请求了同一个字段,所以对应Resolver函数hello也会被执行两次。

虽然这个例子举得不是很好,不过这里主要想表达的是在一个请求中可以解析多个字段,即使是相同的字段也可以在查询的不同地方被多次访问。

再来看下“嵌套”解析器是怎样的:

{
Query: {
author: (root, { id }) => find(authors, { id: id }),
},
Author: {
posts: (author) => filter(posts, { authorId: author.id }),
},
}
这样的解析器可以处理如下查询请求:

query {
author(id: 1) {
firstName
posts {
title
}
}
}
即使解析器的结构是扁平的,但由于它们被不同的类型所引用,所以你还是可以利用它们来实现嵌套查询。想知道GraphQL如何执行请求,请进一步阅读这篇文章:“GraphQL Explained”

点击这里可以查看完整的例子并体验不同的查询效果

上图形象地说明了使用RESTful和GraphQL进行多种资源获取的方式的差异

小结
总的来说,RESTful和GraphQL都提供了很好的API调用方式。如果你对如何构建一个RESTful API足够熟悉,使用GraphQL来实现同样的API功能对你来说并不是一件难事。但GraphQL的一大优势是让你可以在不需要发起多次请求的情况下调用多个函数来获取资源数据。

相同点:

RESTful的端点与GraphQL查询字段都在服务端调起函数执行
RESTful和GraphQL都使用框架和类库来进行一些通用的网络协议处理
差异点:

一个RESTful请求对应一个路由处理器(Route Handler);而一个GraphQL的请求可以唤起多个解析器(Resolver)在一次响应中访问多种资源
RESTful需要你自己构建整个请求的响应;而GraphQL的请求响应是由查询方指定结构、并由GraphQL进行构建组装的
你可以把GraphQL理解为一个可以在一次请求中进行多个端点调用的系统,差不多算是RESTful的多路复用版。

GraphQL和RESTful的区别相关推荐

  1. RPC和RESTful的区别

    文章目录 RPC 进程间通信几种解决方案: 管道(Pipe)或者具名管道(Named Pipe) 信号(Signal) 信号量(Semaphore) 消息队列(Message Queue) 共享内存( ...

  2. RPC 笔记(01)— RPC概念、调用流程、RPC 与 Restful API 区别

    1. 基本概念 PRC 远程过程调用 Remote Procedure Call,其就是一个节点请求另外一个节点提供的服务.当两个物理分离的子系统需要建立逻辑上的关联时,RPC 是牵线搭桥的常见技术手 ...

  3. RESTful源码学习笔记之RPC和 RESTful 什么区别

    REST,即Representational State Transfer的缩写.翻译过来是表现层状态转换. 如果一个架构符合REST原则,就称它为RESTful架构. 啥叫json-rpc? 接口调 ...

  4. 传统接口写法与Restful API 区别

    说到API接口设计有的喜欢用Web Service,有的喜欢用WCF,当然也有还在用最原始的ashx,aspx页面的.无论采用什么方式能很好的满足业务需求就ok,但是不同的方式在扩展性.易用性,可维护 ...

  5. webservice和restful的区别

    REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性.REST提出设计概念和准则为: 1.网络上的所有事物都可以被抽象为资源(res ...

  6. GraphQL 的前世今生

    GraphQL是什么 GraphQL是一种新的API标准,它提供了一种更高效.强大和灵活的数据提供方式.它是由Facebook开发和开源,目前由来自世界各地的大公司和个人维护.GraphQL本质上是一 ...

  7. GraphQL入门基础篇教程

    历史        GraphQL是由Facebook创造的. 当时,Facebook想在移动端实现新闻推送,这不像检索一个故事.作者.故事的内容.评论列表和喜欢该文章的人这么简单,而是每个故事都相互 ...

  8. nodejs 前端 返回数组给_互联网寒冬,一年经验字节跳动、虾皮、快手、拼多多前端面试总结...

    △ 是新朋友吗?记得先点web前端学习圈关注我哦- 题主2019年非985/211非计算机专业本科毕业(野生程序员),之前在腾讯实习了半年多+毕业后在腾讯工作了一年,一直都是前端开发. 年中的时候因个 ...

  9. 惜败虾皮、快手、拼多多,终拿字节 offer

    题主2019年非985/211非计算机专业本科毕业(野生程序员),之前在腾讯实习了半年多+毕业后在腾讯工作了一年,一直都是前端开发. 作者:flytam 来源:https://juejin.cn/po ...

最新文章

  1. Windows XP 源代码泄露,微软终于回应了~
  2. pyhton中的魔术方法
  3. 20162328蔡文琛 四则运算第一周
  4. 性能测试中用LambdaProbe监控Tomcat
  5. linux下安装win xp 进pe出错,PE安装原版XP系统(含高版本PE安装选项灰色处理办法)...
  6. linux 22.3 终端,Linux系统服务Day.22
  7. MySQL(6)视图
  8. jenkins配置ant
  9. 基本农田卫星地图查询_水经注万能地图下载器软件主界面功能说明
  10. 联想年报有看头:供应链展现韧性,PC迎来新机遇
  11. python123新版个人所得税计算_Python 小案例 计算个人所得税
  12. Windows系统IPC$共享与勒索病毒
  13. win7计算机亮度怎么调节,win7系统屏幕亮度怎么修改调整
  14. 斐波纳契数列 python123
  15. js实现局部刷新数据
  16. 谁教会老公出轨外面养情人
  17. elementUI使用卡槽二次封装table(亲测可用)
  18. windows应用程序与控制台应用程序的区别
  19. 《图解密码技术》笔记13:PGP-密码技术的完美组合
  20. 自行车(山地车)拆脚踏

热门文章

  1. 什么是招聘测评工具?
  2. 区块链亲民应用场景大猜想 第一次或将献给超大文件传输
  3. 操作系统概念_第六章_进程同步
  4. 操作系统第五章——进程同步
  5. caffe ssd 测试demo,检测单张图片
  6. 什么是金手指,金手指的设计要求有哪些?
  7. 带您了解如何做好新媒体营销推广
  8. 写一个音乐播放器的微信小程序
  9. Linux指令-唐战伟
  10. Openstack安装与部署三:本地源配置