【GraphQL Java 源码解析】Execution
程序员文章站
2022-03-03 11:57:30
...
Spring boot 执行 GraphQL通过 AbstractGraphQLHttpServlet 执行的
GraphQLSchema schema = GraphQLSchema.newSchema() .query(queryType) .build(); ExecutionInput executionInput = ExecutionInput.newExecutionInput().query("query { hero { name } }") .build(); GraphQL graphQL = GraphQL.newGraphQL(schema) .build(); ExecutionResult executionResult = graphQL.execute(executionInput); Object data = executionResult.getData(); List<GraphQLError> errors = executionResult.getErrors();
1. AbstractGraphQLHttpServlet doGet/doPost 标准的servlet
2. HttpRequestHandlerImpl.handle 构建 GraphQLInvocationInput
3. HttpRequestInvokerImpl.execute
4.GraphQLInvoker.executeAsync 构建 GraphQL
5. GraphQL.executeAsync 构建Execution
6. Execution.execute 构建ExecutionStrategy
7.ExecutionStrategy.execute 递归调用每个field,如果有子field,会递归调用,并返回每个field的调用结果。
for (String fieldName : fieldNames) { CompletableFuture<FieldValueInfo> future = resolveFieldWithInfo(executionContext, newParameters); }
7.1 构建 DataFetchingEnvironment,查找对应的DataFetcher,调用 dataFetcher的get获取每个field的值。
protected fetchField() { DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext) .source(parameters.getSource()) .localContext(parameters.getLocalContext()) .arguments(argumentValues) .fieldDefinition(fieldDef) .mergedField(parameters.getField()) .fieldType(fieldType) .executionStepInfo(executionStepInfo) .parentType(parentType) .selectionSet(fieldCollector) .queryDirectives(queryDirectives) .build(); DataFetcher<?> dataFetcher = codeRegistry.getDataFetcher(parentType, fieldDef); Object fetchedValueRaw = dataFetcher.get(environment); }
7.3 完成一次调用,如果时普通的返回类型,则直接跳出,否则 进入 completeValueForObject,递归调用处理孩子的信息
completeValue() { if (result == null) { fieldValue = completeValueForNull(parameters); return FieldValueInfo.newFieldValueInfo(NULL).fieldValue(fieldValue).build(); } else if (isList(fieldType)) { return completeValueForList(executionContext, parameters, result); } else if (isScalar(fieldType)) { fieldValue = completeValueForScalar(executionContext, parameters, (GraphQLScalarType) fieldType, result); return FieldValueInfo.newFieldValueInfo(SCALAR).fieldValue(fieldValue).build(); } else if (isEnum(fieldType)) { fieldValue = completeValueForEnum(executionContext, parameters, (GraphQLEnumType) fieldType, result); return FieldValueInfo.newFieldValueInfo(ENUM).fieldValue(fieldValue).build(); } // when we are here, we have a complex type: Interface, Union or Object // and we must go deeper // GraphQLObjectType resolvedObjectType; try { resolvedObjectType = resolveType(executionContext, parameters, fieldType); fieldValue = completeValueForObject(executionContext, parameters, resolvedObjectType, result); } catch (UnresolvedTypeException ex) { } return FieldValueInfo.newFieldValueInfo(OBJECT).fieldValue(fieldValue).build(); }
7.4 completeValueForObject调用,构建一个新的ExecutionStrategyParameters参数链,并递归调用7.1的流程
protected completeValueForObject() { ExecutionStrategyParameters newParameters = parameters.transform(builder -> builder.executionStepInfo(newExecutionStepInfo) .fields(subFields) .nonNullFieldValidator(nonNullableFieldValidator) .source(result) ); // Calling this from the executionContext to ensure we shift back from mutation strategy to the query strategy. return executionContext.getQueryStrategy().execute(executionContext, newParameters); }
7.5 构建 ExecutionResult 并返回最终的输出值。