Java中的GraphQL Server,第I部分:基础知识
从表面上看,没有理由通常使用Node.js编写GraphQL服务器。但是,事实证明,不阻塞等待结果的基于回调的语言可以与GraphQL原理很好地配合。
在深入探讨为什么会发生这种情况之前,让我们首先了解GraphQL服务器在下面如何工作以及如何正确实现它。在第二部分中,我们将拆分实现以仅延迟加载必要的信息。在第三部分(最后一部分)中,我们将使用非阻塞惯用语重写服务器,以提高延迟和吞吐量。
什么是GraphQL?
首先,什么是GraphQL?我会说它位于REST和SOAP之间(很简单!)。这是一个相当轻量级的JSON协议,最适合浏览器和移动应用程序。就像REST一样。另一方面,它具有描述有效属性,操作和有效负载的架构。但是,与SOAP不同的是,该模式是为不断发展而设计的,并且我们对希望接收的数据范围拥有很好的控制权。
那里有很多GraphQL教程,所以让我直接跳到示例。这是描述一些API的相当简单的架构:
老实说,几乎没有什么可解释的。感叹号(!
)表示非空字段(其他所有字段都是可选的)。方括号(如[Item]
:)表示Item
s 的数组。这个非常简单的模式代表了一些在线游戏的对象图。
现在,我们需要某种此API的入口点。这与REST不同,后者的每个资源都有其URL。在GraphQL中,我们显式定义了一组允许查询的静态类型的操作:
该API仅将一个端点公开给fetch currentPlayer
(返回Player
实例),而从来没有null
。
使用GraphQL
GraphQL的独特之处在于可以选择Player
我们感兴趣的属性。最完整的查询如下所示:
这将返回完整的JSON响应,匹配模式以及查询:
那很好笑!使用RESTful API,我只想简单地说/currentPlayer
,服务器将返回类似的响应。为什么要在请求中大量复制架构呢?
这就是GraphQL的强大功能所在。想象一下,你只在玩家的名字和兴趣balance
上的billing
对象。您从服务器获得的所有额外信息都是多余的。使用RESTful接口,您可以选择:
- 为每条信息设计细粒度的资源,这些信息将需要多次服务器往返
- 提供服务于各种信息量的端点的多个版本。如果要精确,端点的数量呈指数增长
- 忍受它,忽略客户端上的额外信息以及服务器上不必要的负载
GraphQL通过强制客户端明确要求某些信息来解决该问题。在我们的示例中,如果我们仅关注玩家的姓名和 balance
:
我们得到了先前响应的子集:
相反,如果另一个消费者需要知道库存物品的名称和点数怎么办?简单!
不同的客户,不同的需求:
实施服务器
实现GraphQL服务器仅在表面上类似于RESTful服务器。一个简单的实现只创建一个完整的响应对象,然后让GraphQL引擎将其剥离为仅由客户端请求的必要属性。这样的实现类似于信息非常丰富的RESTful端点。首先,我们需要一个与我们的模式一对一对应的DTO对象:
我们没有实现控制器,而是实现了所谓的Resolver
:
注意,为了组装Player
实例,我们必须要求几个依赖项来获取数据。一个用于Billing
,一个用于Inventory
,依此类推。依赖关系彼此独立,但是都需要填充Player
。此实现有效,并且如果/currentPlayer
是RESTful端点,则可以称之为一天。但是,对于GraphQL,这种实现是一种反模式。
顺便说一下,运行该程序的最小依赖项集(不包括Spring Boot本身)如下:
我将在上一期中提供完整的Spring Boot应用程序。
想象一下BillingRepository
真的很慢。加载帐单太慢了,如果您不需要此信息,最好避免调用它。例如,此查询显式跳过计费数据:
即使弄清楚当前玩家的名字和分数是非常快的,你仍然要付出载入他或她的账单的代价。更糟的是,GraphQL引擎将剥离所有未请求的数据,因此会丢失额外的工作。在下一部分中将解释在合理的地方编写细粒度的解析器。
有什么问题可以加下qq:2062583349。也可添加vx:admindesire,有java、python、web等习资料和视频课程干货”。欢迎交流!