在项目中,我使用 graphql-java 和 spring boot 和postgreSQL数据库。现在,我想使用3.0.0版中发布的 subscription feature 。不幸的是,关于subsciption函数的应用的信息还不是很成熟。
如何使用graphql-java
订阅来实现实时功能的方法?
答案 0 :(得分:4)
截至最近的graphql-java版本,完全支持订阅。订阅的DataFetcher
必须返回org.reactivestreams.Publisher
,而graphql-java将负责将查询函数映射到结果上。
该功能很好documented并且a complete example使用官方仓库中提供的网络套接字。
对于Spring特定的实现,我无法想象使用Spring's own event mechanism(一个很好的教程here)来构建Publisher
的基础是很难的。
每次有传入订阅时,使用应用程序上下文创建并注册一个新的侦听器:context.addApplicationListener(listener)
将发布到正确的Publisher
。例如。在DataFetcher
:
// Somehow create a publisher, probably using Spring's Reactor project. Or RxJava.
Publisher<ResultObject> publisher = ...;
//The listener reacts on application events and pushes new values through the publisher
ApplicationListener listener = createListener(publisher);
context.addApplicationListener(listener);
return publisher;
当Web套接字断开连接或您以某种方式知道事件流已完成时,您必须确保删除该侦听器。
我实际上没有尝试过这一点,请注意,我只是在大声思考。
另一个选择是直接使用Reactor(有或没有Spring WebFlux)。有一个使用Reactor和WebSocket的示例(通过GraphQL SPQR Spring Boot Starter)here。
您可以像这样创建Publisher
:
//This is really just a thread-safe wrapper around Map<String, Set<FluxSink<Task>>>
private final ConcurrentMultiRegistry<String, FluxSink<Task>> subscribers = new ConcurrentMultiRegistry<>();
@GraphQLSubscription
public Publisher<Task> taskStatusChanged(String taskId) {
return Flux.create(subscriber -> subscribers.add(taskId, subscriber.onDispose(() -> subscribers.remove(taskId, subscriber))), FluxSink.OverflowStrategy.LATEST);
}
然后从其他地方推送新值(可能是相关的突变或反应式存储),如下所示:
subscribers.get(taskId).forEach(subscriber -> subscriber.next(task));
E.g。
@GraphQLMutation
public Task updateTask(@GraphQLNonNull String taskId, @GraphQLNonNull Status status) {
Task task = repo.byId(taskId); //find the task
task.setStatus(status); //update the task
repo.save(task); //persist the task
//Notify all the subscribers following this task
subscribers.get(taskId).forEach(subscriber -> subscriber.next(task));
return task;
}
使用SPQR Spring Starter,这就是为您提供与Apollo兼容的订阅实现所需的一切。
答案 1 :(得分:0)
我遇到了同样的问题,我在lib上加入了与spring boot集成的问题。我找到了graphql-java,但是,它似乎只支持模式级别的“订阅”,它没有对此功能执行任何跨国支持。意思是你可能需要自己实现它。
请参阅https://github.com/graphql-java/graphql-java/blob/master/docs/schema.rst#subscription-support
答案 2 :(得分:0)
记录:这是另一个非常好的紧凑示例,它实现了GraphQL的基本功能查询,变异和订阅:https://github.com/npalm/blog-graphql-spring-service