「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
GraphQL是一个从服务端检数据的查询语言。某种程度上,是REST、SOAP、或者gRPC的替代品。
假设我们要从在线商店的后台查询一本特定书记的详细信息。
使用GraphQL,你可以发送以下的查询到服务端来获取id为“book-1”的书籍的详细信息。
这不是JSON,虽然看起来很像。他是一个GraphQL查询语句。语句的含义是:
- 查询指定id的一本书
- 返回书籍的id、name、pageCount、author
- 对于author字段,还需要包含firstName和lastName
返回结果是一个正常的JSON格式:
GraphQL一个非常重要的特性--它是静态类型的:服务端明确的知道你可以查询的每个对象的类型,客户端可以从服务端获取“schema”。Schema描述了哪些查询是可能的,哪些字段能被获取到。(注意:我们这里说的Schema指的是GraphQL Schema,他与其他Schema比如JSON Schema获取DataBase Schema无关)
上面查询的Schema如下所示:
这个教程将重点介绍如何使用Schema在java中实现一个GraphQL服务。
GraphQL Java是GraphQL的Java服务端的实现。在GraphQL Java Github org上有几个仓库。最重要的一个是GraphQL Java Engine(github.com/graphql-jav…
GraphQL Java Engine只关心查询的执行。它不处理任何HTTP或者JSON相关的事。基于这些方面,我们将用GraphQL Java Spring Boot适配器,它负责通过SpringBoot基于HTTP暴露我们的API。
创建一个GraphQL Java服务主要的步骤:
- 定义GraphQL Schema
- 决定一个查询如何获取到数据
我们的示例项目将会写一个简单的接口:获取指定书记的详细信息。虽然这不是一个全面的API,但对于本教程来说足够了。
导入3个包:
前2个是GraphQL Java和GraphQL Java Spring。Guava不是必要的,但是它能让我们更方便点。
在src/main/resources下面创建一个新文件schema.graphqls,写入一下内容:
这个Schema定义了一个顶级字段(在Query类型中):bookById,它返回指定熟记的详情。
它也定义了类型Book,包含字段:id,name,pageCount,author。author的类型是Author,这个在Book类型之后也定义了。
上面用来描述Schema的专用语言叫做Schema Definition Language 或者叫DSL。更多细节可以查看:graphql.org/learn/schem…
这个文件完成功后,我们就得使用它。
我们创建一个新的类GraphQLProvider,定义一个init方法,这个方法用来创建GraphQL实例:
我们使用Guava的Resources去读取之前创建的文件。接下来创建GraphQLSchema和GraphQL实例。这个GraphQL实例通过带有@Bean注解的graphQL()方法作为一个Spring Bean被暴露。GraphQL Java Spring适配器将使用GraphQL实例让我们的schema生效,通过HTTP,默认url: /graphql。
我们还需要做的就是实现buildSchema方法,该方法创建GraphQLSchema实例,连接sdl和DataFetcher。
TypeDefinitionRegistry是schema文件的解析版本。SchemaGenerator将TypeDefinitionRegistry和RuntimeWiring结合起来,生成GraphQLSchema。
buildWiring方法使用graphQLDataFetchers bean去注册2个。
- 一个是通过指定id检索book
- 一个是获取指定book的author
和如何实现 bean在下部分内容说明。
创建和实例总体过程如下所示:
也许GraphQL Java server最重要的概念就是:在查询执行的时候,一个获取一个字段的数据。
当GraphQL Java在执行一个查询时,它会为查询语句中的每个字段调用合适的。一个是一个接口,其中只有一个方法,发发只有一个参数:
重点:schema中的每个字段都有一个与之关联。如果你没有给某个字段定义一个,那么会使用默认的。我们稍后会消息讨论这点。
我们接下来创建一个新类,它包含books和authors的样例list。
完整的实现如下所示:
我们从这个类中的静态列表里获取books和authors,这会帮助你理解GraphQL对数据来源没有任何要求。这是GraphQL的优势:数据可以来自内存里的静态数据,来自数据库或者外部服务。
我们第一个方法返回一个的实现--使用返回指定的book。这个例子的意思是,我们需要从字段拿到id参数,然后找到这个id对应的book。如果没有找到,返回null。
中的“id”指的是在schema中的query字段:
第二个方法,返回一个的实现--获取指定book的author。和book的DataFetcher方法比较,这个我们没有获取参数,但是我们有一个book的实例。通过方法可以获取到有效的父类字段,然后得到结果。这是一个重要的概念:GraphQL中每个字段的都是以自顶向下的方式被调用,父类的结果是子类的属性。
我们接下来使用前面获取的book拿到,然后使用和查询书相同的方式查询指定的author。
我们只实现了2个。正如前面提及的,如果你没有实现,那么就会使用默认的。按我们的例子来讲,意思就是说,,,,,都有一个默认的分别与之关联。
通过多种方式尝试在Java对象上获取属性。例子中很容易通过key查找属性。这对我们来说很好,因为book和Author的Maps的keys和schema中字段是一模一样的。比如,schema中我们定义Book类型的字段,book的返回的Map中有key . 因为字段名字和Map中的key一样,所以才能起作用。
让我们假设一下,我们有一个字段不匹配,book Map中的key是totalPages,而不是pageCount。这将会导致所有book的pageCount值为null,因为无法获取到正确的值。为了解决这个问题,你需要为Book.pageCount去注册一个新的,所下所示:
这就是构建GraphQL API所需要的全部内容。在运行SpringBoot项目后,使用地址下能看到API了。
尝试和查看GraphQL API最简单的方式是使用GraphQL Playground(www.graphql-java.com/tutorials/g…
启动之后你会要求输入一个URL,输入:http://localhost:8080/graphql
之后,你就可以查询我们之前写的样例API。
上面所讲的,引用了2个jar包,graphql-java是GraphQL的java实现形式。graphql-java-spring-boot-starter-webmvc是为了支持SpringWeb方式请求。
而graphql-java-kickstart是在这之上,不仅包含graphql-java,还有graphql-java-tools、graphql-java-servlet。支持了图形界面,我们只需要引入这一个依赖就可以了。
这两个都是graphql语法执行图形界面。
开启方式如下:
和之前所讲一样,需要创建schema文件,后缀必须是。
Schema中定义的每一个数据都需要有一个对应的Java对象:
和之前不一样的是,这个不需要我们写详细的解析步骤,只需要写一个Resolver。
@Component注解是为了被Spring发现。GraphQLQueryResolver接口是为了标记为Schema的解析类。方法名字必须和schema中定义的查询名字一样。
启动SpringBoot后,浏览器访问:http://localhost:8080/playground。就会进入图形界面
左边有2个按钮,DOCS和SCHEMA。DOCS会显示你定义的查询,以及可以获取到的详细信息。SCHEMA会显示你定义的SCHEMA。
如下所示,请求地址为:localhost:8080/graphql 请求方式为POST 参数为{"query":"graphql语句"}
- 前端不需要多次请求,一次请求就可以获取所需数据
- 前端自己决定需要获取的数据
- API文件是及时更新的
语法:graphql.cn/learn/
源码:github.com/graphql-jav…
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/java-jiao-cheng/5746.html