
3.3 编写GraphQL应用
3.3.1 案例简介
本案例介绍基于 Quarkus 框架来实现 GraphQL的基本功能。通过阅读和分析在 Web上实现的基于 GraphQL 语言的查询、新增、删除操作等案例代码,可以理解和掌握基于 Quarkus 框架的GraphQL使用方法。
基础知识:GraphQL应用和MicroProfile GraphQL规范。
GraphQL既是一种用于API的查询语言,也是一个满足数据查询的运行时环境。GraphQL为应用系统API中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余。这一功能也让API更容易地随着时间的推移而演进,还能用于构建强大的开发者工具。关于GraphQL的详细内容可参考其官网上的资料。
MicroProfile GraphQL规范的目的是提供一组“代码优先”的 API,使用户能够在 Java中快速开发基于 GraphQL 的可移植应用程序。本规范的所有实现有两个主要目的:①生成并促使 GraphQL 模式可用,这是通过查看用户代码中的注解来完成的,并且必须包括所有GraphQL 查询和变异,以及通过查询和变异的响应类型或参数隐式定义的所有实体;②执行GraphQL请求,这将以查询或变异的形式出现。
3.3.2 编写程序代码
编写程序代码有 3种方式。第 1种方式是通过代码 UI来实现的,在 Quarkus 官网的生成代码页面中按照指定步骤生成脚手架代码,然后下载文件,将项目引入 IDE 工具中,最后修改程序源码。
第2种方式是通过mvn来构建程序,通过下面的命令创建Maven项目来实现:

第3种方式是直接从GitHub上获取代码,可以从GitHub上克隆预先准备好的示例代码:

该程序位于“023-quarkus-sample-graphql”目录中,是一个Maven工程项目程序。
在IDE工具中导入Maven工程项目程序,在pom.xml的<dependencies>下有如下内容:

quarkus-smallrye-graphql是Quarkus 整合了SmallRye的GraphQL实现。
quarkus-sample-graphql程序的应用架构(如图3-13所示)表明,外部访问ProjectResource资源接口,ProjectResource 调用 ProjectService 服务,ProjectResource 资源依赖于 SmallRye Mutiny框架,GraphQL运行遵循MicroProfile GraphQL规范。

图3-13 quarkus-sample-graphql程序应用架构图
quarkus-sample-graphql程序的核心类如表3-3所示。
表3-3 quarkus-sample-graphql程序的核心类

下面讲解 quarkus-sample-graphql 程序中的 ProjectResource 资源类、ProjectService 服务类和Project实体类的功能和作用。
1.ProjectResource资源类
用IDE工具打开com.iiit.quarkus.sample.graphql.ProjectResource类文件,其代码如下:


程序说明:
①ProjectResource类的作用还是与外部进行交互,该程序实现了GraphQL的CRUD操作。
②@GraphQLApi注解:表明引入GraphQL的API方法。
③@Query("projects")注解:查询路径,类似于REST的GET方法。
④@Mutation注解:在数据被创建、更新或删除时使用,类似于REST的POST、PUT和DELETE方法。
2.ProjectService服务类
用 IDE工具打开 com.iiit.quarkus.sample.graphql.ProjectService类文件,ProjectService类主要给ProjectResource提供业务逻辑服务,其代码如下:



程序说明:
①服务类内部有一个变量Set<Project>,用来存储所有的Project对象实例。该服务实现了对Set<Project>的全部列出、查询、新增、修改和删除等操作功能。
② ProjectService构造阶段,实例化了8个Project对象,然后建立了这8个Project对象之间的父子层次。
3.Project实体类
用 IDE 工具打开 com.iiit.quarkus.sample.graphql.Project 类文件,实体类主要就是基本的POJO对象,其代码如下:


程序说明:Project类一定是一个标准的 JavaBean,即内部字段都是私有变量,通过 get和set方法来赋值和取值。
该程序动态运行的序列图(如图 3-14所示,遵循 UML 2.0规范绘制)描述了外部调用者Actor、ProjectResource和ProjectService等3个对象之间的时间顺序交互关系。
该序列图中总共有5个序列,分别介绍如下。
序列1活动:① 外部调用ProjectResource资源类的Query(list)方法;② Query(list)方法调用ProjectService服务类的list方法;③返回整个Project列表。
序列 2活动:① 外部传入参数 ID并调用 ProjectResource资源类的 Query(getById)方法;② Query(getById)方法调用 ProjectService服务类的 getById方法;③ 返回 Project列表中对应ID的Project对象。
序列3活动:① 外部传入参数Project对象并调用ProjectResource资源类的Mutation(add)方法;② Mutation(add)方法调用 ProjectService服务类的 add方法,ProjectService服务类实现增加一个Project对象的操作并返回整个Project列表。
序列 4 活动:① 外部传入参数 Project 对象并调用 ProjectResource 资源类的Mutation(update)方法;② Mutation(update)方法调用 ProjectService 服务类的 update 方法,ProjectService 服务类根据项目名称是否相等来实现修改一个 Project 对象的操作并返回整个Project列表。
序列 5 活动:① 外部传入参数 Project 对象并调用 ProjectResource 资源类的 Mutation (delete)方法;② Mutation(delete)方法调用 ProjectService 服务类的 delete 方法,ProjectService服务类根据项目名称是否相等来实现删除一个Project对象的操作并返回整个Project列表。

图3-14 quarkus-sample-graphql程序动态运行的序列图
3.3.3 验证程序
通过下列几个步骤(如图3-15所示)来验证案例程序。

图3-15 quarkus-sample-graphql程序验证流程图
下面对其中涉及的关键点进行说明。
1.启动quarkus-sample-graphql程序服务
启动程序有两种方式,第 1种是在开发工具(如 Eclipse)中调用 ProjectMain类的 run方法,第2种是在程序目录下直接运行命令mvnw compile quarkus:dev。
2.通过API显示全部schema内容
在命令行窗口中键入命令 curl http://localhost:8080/graphql/schema.graphql,或在浏览器中输入URL(http://localhost:8080/graphql/schema.graphql),获得的结果是schema列表,是JSON格式的:


schema内容说明如下:
①Query有2个方法,分别是project和projects方法。
②Mutation有3个方法,分别是add、delete、update方法。
③Project对象结构。
④输入的Project对象结构。
3.GraphQL的查询和处理
接着,通过专业工具来进行查询和处理,打开浏览器 URL(http://localhost:8080/graphql-ui/),会显示如图3-16所示的graphql-ui界面。

图3-16 graphql-ui界面
可以在输入框中键入如下查询内容:

然后单击“执行”按钮,会显示如图3-17所示的结果。

图3-17 显示查询结果界面
4.通过界面工具获取Project列表及其内部全部数据
为了获取所有数据及其内部的层次数据,可以在界面工具窗口中输入如下GraphQL语句:


结果界面如图3-18所示。

图3-18 查询全部数据的结果界面
具体的结果内容如下:



这与我们的初始化数据完全一致。
5.通过界面工具获取一条Project数据
按照JSON格式获取一条Project数据,在界面工具窗口中输入如下GraphQL语句:

结果是项目id为1的JSON列表。
6.通过界面工具新增一条Project数据
按照JSON格式增加一条Project数据,在界面工具窗口中输入如下GraphQL语句:

7.通过界面工具修改一条Project数据
按照JSON格式修改一条Project数据,在界面工具窗口中输入如下GraphQL语句:

通过结果,可以观察到已经修改了数据内容。
8.通过界面工具删除一条Project数据
按照JSON格式删除一条Project数据,在界面工具窗口中输入如下GraphQL语句:

通过结果,可以观察到已经删除了数据内容。