如何在 Spring Boot + GraphQL Java 工具的上下文中执行对 GraphQL 的 Java 调用?

How to execute Java calls to GraphQL in a Spring Boot + GraphQL Java Tools' context?

在 Spring 启动应用程序中,我们已经拥有功能齐全的 GraphQL 端点,通过 GraphQL Java 工具提供 .graphqls 文件(我们包括 graphql-spring-boot-starter依赖)并通过我们的基础 Query class 实现 GraphQLQueryResolver 和后续的 GraphQLResolver 来处理数据解析。

出于业务需要,我们必须重新创建标准 REST API 端点,所以我想知道为什么不直接调用 GraphQL(而不必重新实现 "by hand" 数据再次决议)? 并且因为它在同一个后端应用程序中,不需要进行 HTTP 或 servlet (ForwardRequest) 调用,只需在 Java 中调用一些 API。 问题是我不知道如何进行。

我阅读了这个示例,但它使用的是基本的 GraphQL Java(不是工具): https://www.graphql-java.com/documentation/v9/execution/

我知道这应该是可能的,因为我们被允许在测试中这样做: https://github.com/graphql-java-kickstart/graphql-spring-boot/blob/master/example-graphql-tools/src/test/java/com/graphql/sample/boot/GraphQLToolsSampleApplicationTest.java

但是如何在常规代码中做到这一点?没有 GraphQLTemplate.

这样的东西

我还尝试在以下位置搜索示例:

但没有找到与我们需要相关的内容。

在文档中找不到更多内容:

我错过了什么?理想情况下,我希望像这样注入一些 GraphQLSomething

@RestController
@RequestMapping(path = "api")
public class CompanyController {

    @Autowired
    private GraphQLSomething graphQLSomething;

    @GetMapping("company/{id}")
    public ResponseEntity<?> societe(@PathVariable @NotNull Integer id) {
        GraphQLSomethingResult result = GraphQLSomething.query("company(id: $id) { id name andsoone }", "{ \"id\": 123456 }").execute(); // not really sure of the GraphQL syntax here, but it'll need some tests...
        return result.getDataOrElse();
    }

}

终于找到了我想要的方法:

import java.util.Map;
import java.util.Optional;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.ImmutableMap;

import graphql.ExecutionResult;
import graphql.servlet.core.GraphQLQueryInvoker;
import graphql.servlet.core.internal.GraphQLRequest;
import graphql.servlet.input.GraphQLInvocationInputFactory;
import graphql.servlet.input.GraphQLSingleInvocationInput;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Validated
@RestController
@RequestMapping(path = "api")
public class CompanyController {

    @Autowired
    private GraphQLInvocationInputFactory invocationInputFactory;

    @Autowired
    private GraphQLQueryInvoker queryInvoker;

    @GetMapping("company/{id}")
    public ResponseEntity<?> societe(@PathVariable @NotNull Integer id) {
        String query = "query ($id: Int!) { company(id: $id) { id name andsoon } }";
        /*
         * ImmutableMap is a Guava class; you can build the map (e.g. a HashMap) on your
         * own, or simply Map.to(..) in Java 9, or even @PathVariable Map<String,
         * Object> variables as the method's parameter instead (but you'll miss the
         * validation).
         */
        Map<String, Object> variables = ImmutableMap.of("id", id);

        GraphQLRequest request = new GraphQLRequest(query, variables, null);
        GraphQLSingleInvocationInput invocationInput = invocationInputFactory.create(request);
        ExecutionResult result = queryInvoker.query(invocationInput);

        /*
         * Of course result.getData() can be null here - see also result.isDataPresent()
         * - but data/error handling's left to you
         */
        Optional<Object> company = Optional.ofNullable(result.getData().get("company"));
        return ResponseEntity.of(company);
    }

}

仅供参考,要获取上述代码的依赖项,您需要:

    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphql-spring-boot-autoconfigure</artifactId>
        <version>5.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphql-java-servlet</artifactId>
        <version>6.1.3</version>
    </dependency>