在Spring Boot应用程序中,我们已经有一个功能齐全的GraphQL端点,通过GraphQL Java工具提供.graphqls
文件(我们包含了graphql-spring-boot-starter
依赖项(,并通过实现GraphQLQueryResolver
和后续GraphQLResolver
的基Query
类来处理数据解析。
对于业务需求,我们必须重新创建标准的 REST API 端点,所以我想知道为什么不直接调用 GraphQL(而不必再次"手动"重新实现数据解析(? 由于它位于同一个后端应用程序中,因此无需进行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
这样的东西.
我还尝试在以下位置搜索示例:
- https://github.com/graphql-java-kickstart/graphql-java-tools/tree/master/example
- https://github.com/graphql-java-kickstart/graphql-spring-boot
但发现没有与我们的需求相关。
在文档中找不到更多内容:
- https://www.graphql-java-kickstart.com/tools/
- https://www.graphql-java-kickstart.com/spring-boot/
我错过了什么?理想情况下,我希望注入一些这样的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>