欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【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 并返回最终的输出值。