如何解决使用graphql-java构建中继GraphQL服务器
我们正在使用graphql-java来构建graphql服务器,并且无法遵守Relay规范。根据中继规范,必须通过单个查询node(id: ID)
可检索所有节点。 graphql-java文档显示了对Relay节点接口的支持,但是实际实现此功能的文档很少。我们遇到的确切问题是了解如何为节点查询生成通用查询? Relay Todo示例:https://github.com/graphql-java/todomvc-relay-java显示了使用单个datafetcher的极其简单的基于代码的方法,此处的示例无需“读取”节点“类型”或将请求委托给正确的dataFetcher。
schema.graphqls:
type Query {
node(id: ID!): Node
user(id: ID!): User
otherType(id:ID!): OtherType
}
interface Node {
id: ID!
}
type User implements Node {
id: ID!
firstName: String
lastName: String
}
type OtherType implements Node {
id: ID!
description: String
stuff: String
}
我们当前正在使用SDL生成我们的模式(如下所示)
@Bean
private GraphQLSchema schema() {
Url url = Resources.getResource("schema.graphqls");
String sdl = Resources.toString(url,Charsets.UTF_8);
GraphQLSchema graphQLSchema = buildSchema(sdl);
this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
return graphQLSchema;
}
private GraphQLSchema buildSchema(String sdl) {
TypeDeFinitionRegistry typeRegistry - new SchemaParser().parse(sdl);
RuntimeWiring runtimeWiring = buildWiring();
SchemaGenerator schemaGenerator = new SchemaGenerator();
return schemaGenerator.makeExecutableSchema(typeRegistry,runtimeWiring);
}
private RuntimeWiring buildWiring(){
return RuntimeWiring.newRuntimeWiring()
.type(newTypeWiring("Query")
.dataFetcher("user",userdispatcher.getUserById()))
.type(newTypeWiring("Query")
.dataFetcher("otherType",otherTypedispatcher.getotherTypeById()))
.type(newTypeWiring("Query")
.dataFetcher("node",/*How do we implement this data fetcher? */))
.build()
}
大概,我们必须连接数据提取器,如上面的最后一行所示。但是,这是文档开始变得朦胧的地方。以上是否符合中继规范?
无论基础类型(用户,OtherType等)如何,我们将如何实现单节点dataFetcher,该数据返回对任何单个节点的引用?解决方法
是的,您需要实现一个节点数据提取程序,该数据提取程序将从Node ID中返回一个Node。
我将假设您正在使用基础sql数据库:Node可以是任何类型,这意味着您不能将数据库ID用作Node ID(因为两个不同类型的节点可能具有相同的数据库ID )。您需要构建自己的Node ID。
构建此类ID的一种简单方法是将对象类型和对象ID串联在一起。例如:“ User:4234”。
根据中继graphql服务器规范指定:
我们得到的ID是base64字符串。 ID设计为不透明 (唯一应传递给节点上id参数的是 查询系统中某个对象的id的结果不变,并且 base64字符串是GraphQL中有用的约定,用于提醒查看者 该字符串是一个不透明的标识符。
我们需要将节点ID编码/解码为以64为底。
下面的代码尚未经过测试,但是可以使您了解如何进行操作。
DataFetcher dataFetcher = new DataFetcher() {
@Override
Object get(DataFetchingEnvironment environment) {
Object argument = environment.getArgument("id");
if(argument instanceof String) {
String node = (String) argument;
//TODO decode base 64 nodeId
//TODO split nodeId into String `nodeType` and Long `id`
//TODO retrieve your object of type `nodeType` and id `id`
}
}
}
,
架构中的 Node 接口需要 TypeResolver 和 Data Fetcher 实现。
即使你提供了一个数据获取器实现并按照 AllirionX 的建议将其连接起来,你仍然需要为 Node 接口提供一个解析器来帮助 graphql-java 理解它应该解析哪个具体的对象类型。
.type(newTypeWiring("Query").dataFetcher("node",new NodeDataFetcher()))
类似这样的 -
.type(newTypeWiring("Node").typeResolver(new TypeResolver() {
@Override
public GraphQLObjectType getType(TypeResolutionEnvironment env) {
return null;
}
}))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。