在代码中查看 graphql-java 相关库之间的关系

如果在Spring Boot等框架中使用graphql-java,为了方便使用,还需要导入其他各种库。
这是因为graphql-java只具有基本的API,无法单独处理与Web端的连接和Subscription的支持。
由于我自己对这些关系并不清楚,只是阅读了文档的信息,所以我在这篇文章中将记录我通过阅读代码所了解到的内容。

前提是指在进行推理或讨论之前必须先建立的基础条件。

如果在使用Spring Boot + Kotlin的情况下考虑使用graphql-java-tools,我已经在公司的博客中写了关于这方面的内容,您也可以参考一下。

我们将使用以下的库。

    • graphql-java

https://github.com/graphql-java/graphql-java

graphql-java-servlet

https://github.com/graphql-java-kickstart/graphql-java-servlet

graphql-java-tools

https://github.com/graphql-java-kickstart/graphql-java-tools

graphql-spring-boot-starter

https://github.com/graphql-java-kickstart/graphql-spring-boot

形成

大致来说,graphql-java提供GraphQL的核心功能,而graphql-java-tools使得调用graphql-java的基本API更方便。
graphql-java-servlet使用servlet API使得可以在网络上使用graphql-java,
graphql-spring-boot-server将graphql-java-servlet与Spring Boot结合,使得在依赖注入的开发方式下更加容易。
说实话,有很多东西让人困惑。我之前也是使用Rails,所以一开始完全不知道为什么要用这个库,如果去掉它会怎样,还有很多事情我现在也不太明白。
所以如果有错误,请指正。

从代码的角度来看关系

话题有些偏离,但是在阅读代码时,我下载了各种仓库来进行阅读,并通过实际创建样例应用程序并进行调试运行的组合技巧来理解。
在这个过程中,我通过这个样例应用程序进行了操作确认。虽然库的版本有点旧,但整体框架应该没有变化,所以我没有进行更新(如果有变化,我会很伤心)。

关系依赖

    • graphql-java

大元のコア機能

graphql-java-servlet

graphql-java に依存

graphql-java-tools

graphql-java に依存

graphql-spring-boot-starter

同リポジトリの graphql-spring-boot-autoconfigure を経由して、graphql-java, graphql-java-tools, graphql-java-servlet に依存

graphql-java 和 graphql-java-servlet 的关系。

graphql-java没有单独的接收HTTP请求的接口。因此,用于通过HTTP创建GraphQL功能的库是graphql-java-servlet。
正如其名称所示,通过AbstractGraphQLHttpServlet继承HttpServlet的GraphQLHttpServlet在库中定义。
在AbstractGraphQLHttpServlet中,覆盖了doGet、doPost方法,以便可以在HTTP中进行请求和响应,
并通过GraphQLQueryInvoker类调用graphql-java的API,返回处理GraphQL的结果。

graphql-java 和 graphql-java-tools 的关系是什么?

graphql-java-tools 在生成用于使用 graphql-java 的 GraphQLSchema 的过程中,提供了一种机制,通过定义包含了 GraphQL 的每个类型字段的解析器函数和定义表示每个类型的数据类,以简化该过程。浏览 graphql-java 的架构定义文档确实可以看出,这个过程似乎相当繁琐,相比其他语言提供的机制,确实可以找到更简单的方法。正因为如此,graphql-java-tools 能够弥补这一点并提供便利之处。

使用SchemaParserBuilder来定义一个模式文件,并传递一个继承自GraphQLResolver的Resolver类给SchemaParser类来生成(需要注意graphql-java库中也有同名类但有所不同)。在解析模式定义时使用了graphql-java库的Parser类(因此这里是与graphql-java共享的处理),通过调用parseDocument获取定义并在内部使用。

通过调用 SchemaParser 类的 makeExecutableSchema 方法可以生成 GraphQLSchema。在 makeExecutableSchema 中调用的 toSchema 方法可以看到,根据 SchemaObjects 的实现可以理解到,它使用了 graphql-java 的 GraphQLSchema 构建器来生成 GraphQLSchema。toSchema 方法所需的参数是用于每个 query/mutation/subscription 的 GraphQLObjectType,并在传递到这里之前,已经根据模式和每个 Resolver 的信息转换为了 GraphQLObjectType 的状态。

GraphQLObjectType转换是通过SchemaParser类的parseSchemaObjects方法调用的,它在createObject方法中完成。createObject方法使用GraphQLObjectType生成器定义与GraphQL类型对应的对象,并生成GraphQLObjectType。同时,还会对对象的字段进行定义,并使用fieldResolversByType(稍后详述)设置字段的DataFetcher。

fieldResolversByType 是一个以 ObjectTypeDefinition 为键,MutableMap<FieldDefinition, FieldResolver> 为值的 Map,在 SchemaParser 类的构造函数中从传入的 ScannedSchemaObjects 获取。ScannedSchemaObjects 是由 SchemaParserBuilder 类中的 scanForClasses 方法生成的类。观察每个 Resolver 的操作,可以看到,在 SchemaClassScanner 中,首先将 Resolver 的信息加入到继承了 ResolverInfo 的各个类中。然后,在 scanResolverInfoForPotentialMatches 方法中,根据传入的 ResolverInfo 生成与对象字段匹配的 FieldResolver,并将 ObjectTypeDefinition 作为键与 FieldDefinition 一起设置到 fieldResolversByType 中。由于每个继承了 FieldResolver 的类都有一个用于生成DataFetcher的createDataFetcher方法,因此可以使用此方法将每个 Resolver 映射到对应的字段上。FieldResolver 定义了 MethodFieldResolver、PropertyFieldResolver 和 PropertyMapResolver,会被正确映射到各个类上。

虽然有些地方我还是有点模糊理解,但总体的走向应该是这样的吧。

graphql-spring-boot-starter 与各个库的关系

这个库将上述 graphql-java、graphql-java-servlet 和 graphql-java-tools 结合起来,以类似于Spring Boot的依赖注入机制来使用。

graphql-spring-boot-starter 的实现基本上在相同的存储库中,称为 graphql-spring-boot-autoconfigure,因此我们将以这段代码为基础进行解释。

在 graphql-spring-boot-autoconfigure 中,存在着由 Spring Framework 的 @Configuration 注解修饰的类,并且它们的后缀是 XxxAutoConfiguration。除了针对 WebSocket 的配置外,本文将重点讨论 GraphQLJavaToolsAutoConfiguration 和 GraphQLWebAutoConfiguration。

GraphQLJavaToolsAutoConfiguration 是为 graphql-java-tools 提供的配置,其目的是为了创建一个基于 graphql-java 的 GraphQLSchema 的 Bean。为了创建 GraphQLSchema,需要通过 SchemaParser 传入一个 Resolver 的 List<GraphQLResolver<?>> resolvers,并通过 Constructor Injection 来接收。作为使用者,只需编写定义了各种 GraphQLResolver 接口的类即可,在应用启动后,就可以使用 GraphQL 的功能了。由于有了这个配置,graphql-java-tools 能够发挥其真正的价值。

GraphQLWebAutoConfiguration是为graphql-java-servlet提供的一组配置,通过将ServletRegistrationBean\定义为@Bean,将GraphQLHttpServlet(默认情况下)注册为Servlet。有关ServletRegistrationBean的详细信息,请查看此处。传递给GraphQLHttpServlet配置的GraphQLSchema是由GraphQLJavaToolsAutoConfiguration定义的,这样就可以从GraphQL模式定义中使用在HTTP上实际运行的GraphQL功能。

只需提供一种选择即可。
除了 ServletRegistrationBean 外的 @Bean 上附有 @ConditionalOnMissingBean 或 @Autowired(required = false),所以默认行为已经确定,可以覆盖必要的部分。

GraphQLJavaToolsAutoConfiguration 是一个很好的例子,它巧妙地运用了Spring的功能。感觉有点像Rails,对于擅长Ruby和Rails的作者来说是相对容易的。

总结

通过代码阅读,我明确了之前只在文档中理解的部分,对其内容的理解大大加深了。与其他语言不同,我可以直接使用类似于graphql-java-tools的库,相对来说更容易理解。但是,graphql-java会稍微复杂一点,虽然自由度更高,但也稍微有些难度。我认为这可能与我本来就喜欢Ruby和Elixir有关,因为graphql-ruby和Elixir的Absinthe等库非常容易理解(其中graphql-ruby和Absinthe也是以代码为先的库)。
然而,在未来,如果使用Java等来使用GraphQL,我认为通常会选择使用graphql-java-tools,或者与可以轻松定义schema的类似库一起使用,而不是直接使用graphql-java。
另外,在进行本次调查时发现,与graphql-java相关的信息很少,甚至有人扩大了对graphql-java几乎没有被使用的怀疑。
如果有人使用graphql-java,请期待其输出。

请向下列选项参考:
参考资料:
参考原文:
参考建议:
参考方式:
参考解决方案:

GraphQL Java 相关

    • Building a GraphQL Server with Java Backend Tutorial https://www.howtographql.com/graphql-java/0-introduction/

ちょっと古いけどサラッと概要を把握できます

GraphQL Java https://www.graphql-java.com/documentation/

公式のドキュメント。ここ最近(12/06現在)新しくなった。

GraphQL Java Kickstart https://www.graphql-java-kickstart.com/

graphql-java-servlet, graphql-java-tools, graphql-spring-boot-starter の公式ドキュメント。こちらも graphql-java-kickstart organization ができて新しくなったかも。

graphql-java/graphql-java: GraphQL Java implementation https://github.com/graphql-java/graphql-java

graphql-java-kickstart/graphql-java-servlet: Servlet endpoint for GraphQL Java https://github.com/graphql-java-kickstart/graphql-java-servlet

graphql-java-kickstart/graphql-java-tools: A schema-first tool for graphql-java inspired by graphql-tools for JS https://github.com/graphql-java-kickstart/graphql-java-tools

graphql-java-kickstart/graphql-spring-boot: GraphQL and GraphiQL Spring Framework Boot Starters – Forked from oembedler/graphql-spring-boot due to inactivity. https://github.com/graphql-java-kickstart/graphql-spring-boot

关于春天的周围环境

    • Spring FrameworkとDIについて – mookjp.io https://blog.mookjp.io/blog-ja/spring-framework%E3%81%A8di%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/

定期的に mook さんの資料見直している気がする。感謝

相关文章、示例实现、以及其他语言的信息等

    • フロントエンド向けの API サーバリニューアルに GraphQL を検討している話 – エムスリーテックブログ https://www.m3tech.blog/entry/graphql-on-spring-boot-with-kotlin

m3dev/graphql-spring-boot-kotlin-sample https://github.com/m3dev/graphql-spring-boot-kotlin-sample

rmosolgo/graphql-ruby: Ruby implementation of GraphQL https://github.com/rmosolgo/graphql-ruby

Elixir で Absinthe を使って GraphQL に触れてみた – Qiita https://qiita.com/ma2ge/items/52dcebd54c5bdecafcb6

广告
将在 10 秒后关闭
bannerAds