我正在将 GraphQl-java-kickstart 项目迁移到 Spring-GraphQl,因为在项目中实现 GraphQL 时 Spring-GraphQl 不可用。迁移的主要原因是 Spring 提供的自动配置和基于注释的方法可能有助于删除初始 GraphQl 项目中的许多复杂的样板代码。
kickstart 数据加载器配置中有一个数据加载器注册,我似乎无法在新的 Spring Graphql 配置设置中重新创建它。在 kickstart grapql 配置中,创建一个数据加载器并将其用作另一个数据加载器中的方法参数(如下简化):
@Component
public class RequestContextBuilder extends DefaultGraphQLServletContextBuilder {
@Override
public GraphQLKickstartContext build(HttpServletRequest request, HttpServletResponse response) {
Map<Object, Object> map = new HashMap<>();
// ...
return GraphQLKickstartContext.of(buildDataLoaderRegistry(), map);
}
private DataLoaderRegistry buildDataLoaderRegistry() {
var noBatching = new DataLoaderOptions().setBatchingEnabled(false);
var dataLoaderRegistry = new DataLoaderRegistry();
var firstLoader = DataLoaderFactory.newDataLoader(
ids1 -> supplyAsync(() -> firstService.getItems(ids1), traceableExecutorService),
noBatching
);
dataLoaderRegistry.register("first", firstLoader);
var secondLoader = DataLoaderFactory.newDataLoader(
ids2 -> supplyAsync(() -> ((Function<List<ID>, List<Item>>) ids2 ->
secondService.loadUsingOtherLoader(ids2, firstLoader)).apply(ids), traceableExecutorService),
noBatching
);
dataLoaderRegistry.register("second", secondLoader);
return dataLoaderRegistry;
}
}
...
@Service
public class SecondService {
public List<Item> loadUsingOtherLoader(List<ID> ids, DataLoader<ID, Item> firstLoader) {
return ids.stream()
.map(firstloader::load)
. //
.toList();
}
}
我似乎无法使用 BatchLoaderRegistry 在 Spring-GraphQl 配置中重新创建此设置,因为加载程序作为 lambda 而不是 DataLoaders 传递,并且无法从注册表中检索:
@Configuration
public class RequestContextBuilder {
public RequestContextBuilder(BatchLoaderRegistry registry, FirstService firstService, SecondService secondService) {
registry.forName("first")
.withOptions(BATCHING_DISABLED)
.registerBatchLoader((ids, env) -> Flux.fromStream(ids.stream()).map(firstService::getItems));
registry.forName("second")
.withOptions(BATCHING_DISABLED)
.registerBatchLoader((ids, env) -> Flux.fromStream(ids.stream()).map(secondService::loadUsingOtherLoader));
}
}
}
尽管在理想情况下,第二个加载器不需要依赖于第一个加载器,但此迁移的初始阶段是从 graphql-kickstart 切换到 spring-graphql,并进行尽可能少的更改。在稍后的重构阶段,加载器将被解耦,应用弹簧逻辑+注释等。
有谁知道这个问题如何解决吗?
对于任何感兴趣的人,我设法通过使用
BatchLoaderEnvironment
: 检索其他数据加载器来解决此问题
@Configuration
public class RequestContextBuilder {
public RequestContextBuilder(BatchLoaderRegistry registry, FirstService firstService, SecondService secondService) {
registry.forName("first")
.withOptions(BATCHING_DISABLED)
.registerBatchLoader((ids, env) -> Flux.fromStream(ids.stream()).map(firstService::getItems));
registry.forName("second")
.withOptions(BATCHING_DISABLED)
.registerBatchLoader((ids, env) -> {
var dfe = obtainDfeFromEnvironment(env);
var firstLoader = dfe.getDataLoader("first");
// .... etc
});
}
private static DataFetchingEnvironment obtainDfeFromEnvironment(BatchLoaderEnvironment env) {
return env.getKeyContextsList().stream()
.filter(DataFetchingEnvironment.class::isInstance)
.map(DataFetchingEnvironment.class::cast)
.findFirst()
.orElseThrow();
}
}
并在调用数据加载器时将
DataFetchingEnvironment
作为第二个参数传递:
dfe.<SomeId, List<SomeClass>>getDataLoader("second").load(someId, dfe);