如何在Java中使GraphQL进行异步/并行/并发查询? (里面的代码示例)

时间:2019-01-26 13:22:12

标签: java spring-boot graphql graphql-java

我目前在java 8中有一个项目。

如果我仅使用:

    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphql-spring-boot-starter</artifactId>
        <version>5.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.graphql-java</groupId>
        <artifactId>graphiql-spring-boot-starter</artifactId>
        <version>4.0.0</version> <!--5.0.2 http://localhost:8999/graphiql fails to load-->
    </dependency>

并具有如下模式:

type Query {
    getAllItems: [TestEntity]
    getItem(dictionaryType: String): TestEntity
    }

    type TestEntity {
    code: String!
    name: String
    description: String
    dictionaryType: String
}

1) 并使resolver像这样:

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class QueryResolver implements GraphQLQueryResolver {
    @Autowired
    private final DictionaryService dictionaryService;

    public List<TestEntity> getAllItems() {
        return dictionaryService.getAllDictionaryItemsAsStrings();
    }

    public TestEntity getItem(String dictionaryType) {
        return dictionaryService.getDictionaryItemsFirstAsString(dictionaryType);
    }
}

如果我立即请求two资源:

query {
    getAllItems {
        code
        description
    }
        getItem(dictionaryType: "test1") {
        code
        name
        description
    }
}

getItemgetAllItems执行asynchronusly / parralel / concurrently还是一次执行任务?

2) 如果我们使用相同的架构但使用实现`resolver的代码来更改代码,则这样:

@RestController
@PreAuthorize("isAuthenticated()")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GraphqlController {
    private final DictionaryService dictionaryService;

    private DataFetcher<List<TestEntity>> allDictionaryItemsFetcher;
    private DataFetcher<TestEntity> dictionaryItemFetcher;

    @Value("classpath:test-resolvers.graphqls")
    private Resource schemaResource;
    private GraphQL graphQL;

    @PostConstruct
    private void loadSchema() throws IOException {
        File schemaFile = schemaResource.getFile();
        TypeDefinitionRegistry registry = new SchemaParser().parse(schemaFile);
        RuntimeWiring wiring = buildWiring();
        GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(registry, wiring);
        graphQL = GraphQL.newGraphQL(schema).build();
    }

    private void initializeFetchers() {
        allDictionaryItemsFetcher = dataFetchingEnvironment -> dictionaryService.getAllDictionaryItemsAsStrings();
        dictionaryItemFetcher = dataFetchingEnvironment ->
                dictionaryService.getDictionaryItemsFirstAsString(dataFetchingEnvironment.getArgument("dictionaryType"));
    }

    private RuntimeWiring buildWiring() {
        initializeFetchers();
        return RuntimeWiring.newRuntimeWiring()
                .type("Query", typeWriting -> typeWriting
                        .dataFetcher("getAllItems", allDictionaryItemsFetcher)
                        .dataFetcher("getItem", dictionaryItemFetcher)
                )
                .build();
    }

    @PostMapping("graphql")
    public ResponseEntity<Object> getResource(@RequestBody Map<String, Object> request) {
        ExecutionResult result;
            String query = request.get("query").toString();
            Map<String, Object> variables = (Map<String, Object>) (request).get("variables");

            ExecutionInput input = ExecutionInput.newExecutionInput()
                    .query(query)
                    .variables(variables)
                    .context(SecurityContextHolder.getContext().getAuthentication())
                    .build();

            result = graphQL.execute(input);
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

}

它可能不会异步运行,因为我们需要使用例如CompletableFuture。我不确定如何将代码更改为asynchronous / concurrently / parralel,如果有人也应该这样做,那么我会很高兴。 预先感谢!

编辑:

在示例2)中,我可以这样写:

@PostMapping("graphql")
public DeferredResult<ResponseEntity<?>> handleReqDefResult(@RequestBody Map<String, Object> request) throws ExecutionException, InterruptedException {
    DeferredResult<ResponseEntity<?>> output = new DeferredResult<>();

    CompletableFuture<ExecutionResult>  result;
    String query = request.get("query").toString();
    Map<String, Object> variables = (Map<String, Object>) (request).get("variables");

    ExecutionInput input = ExecutionInput.newExecutionInput()
            .query(query)
            .variables(variables)
            .context(SecurityContextHolder.getContext().getAuthentication())
            .build();

    result = graphQL.executeAsync(input);
    output.setResult(ResponseEntity.ok(result.get()));
    return output;
}

0 个答案:

没有答案