正好有 5 种可能性(从 graphql-java v12 开始)向任何级别的解析器 (DataFetcher) 提供信息:
1) 直接在查询中传递它们(可能在多个级别上):
{customer(id: 3) {
user {
profile(id: 3) {
name
}
}
}
}
2) 从源对象中获取值
source 是封闭查询的结果。
在您的情况下,customer 查询的来源是根(无论您在查询执行时提供什么,例如
graphQL.execute(ExecutionInput.newExecutionInput()
.query(query)
.root(root)
.build())
user 查询的来源是返回的任何 customer 查询,可能是一些 Customer 实例。
profile 查询的来源是 user 查询返回的任何内容,可能是 User 实例。
您可以通过DataFetchingEnvironment#getSource() 获取源代码。因此,如果User 包含您想要的CustomerID,只需通过((User) env.getSource()).getCustomerId() 获取它。如果没有,请考虑将结果包装到一个对象中,该对象将包含您在子查询中需要的所有内容。
3) 使用共享上下文传递值
graphql-java 如果您不自己提供自定义上下文,将为您提供GraphQLContext 的实例。因此,在customer 的DataFetcher 中,您可以将CustomerID 存储到其中:
Customer customer = getCustomer();
GraphQLContext context = env.getContext();
context.put("CustomerID", customer.getId());
稍后,在DataFetcher for profile 中,您可以从上下文中获取它:
GraphQLContext context = env.getContext();
context.get("CustomerID");
要提供自定义上下文,请在执行查询时传递它:
ExecutionInput input = ExecutionInput.newExecutionInput()
.query(operation)
.context(new ConcurrentHashMap<String, Object>())
.build()
graphQL.execute(query, input);
您可以使用类型化对象而不是 ConcurrentHashMap,但您必须确保字段是 volatile 或 getters/setters synchronized 或其他线程安全的。
这种方式是有状态的,因此最难管理,所以只有在其他方法都失败时才使用它。
4) 直接获取传递给父字段的参数(可能从 graphql-java v11 开始)
ExecutionStepInfo stepInfo = dataFetchingEnvironment.getExecutionStepInfo();
stepInfo.getParent().getArguments(); // get the parent arguments
5) 使用 local 上下文传递值(可能从 graphql-java v12 开始)
不是直接返回结果,而是将其包装成DataFetcherResult。这样,您还可以将任何对象附加为 localContext,所有子 DataFetchers 都可以通过 DataFetchingEnvironment#getLocalContext() 使用该对象