【问题标题】:WebFlux not sending data when using application/stream+json使用 application/stream+json 时 WebFlux 不发送数据
【发布时间】:2018-07-23 05:53:18
【问题描述】:

我有一个响应式核心 WebClient 可以发布到给定的端点。有效负载是Job 对象的通量,内容类型是 application/stream+json Flux jobFlux = Flux.just(new Job());

Mono<JsonNode> response = localEP.post().uri( "/dev/job" )
    .contentType(MediaType.APPLICATION_STREAM_JSON)
    .body( BodyInserters.fromObject(jobFlux))
    .retrieve()
    .bodyToMono( JsonNode.class );

在服务器端,我尝试了 Spring Controller 样式和 Spring Web Reactive FunctionHandler 来处理上述调用的负载,负载是 Flux。

  @PostMapping(path = "/dev/job", consumes = MediaType.APPLICATION_STREAM_JSON_VALUE)
  @ResponseStatus( HttpStatus.CREATED )
 public Mono<Void> loadJobs (@RequestBody Flux<Job> jobs) {
    return this.repository.create(jobs); 
 }

域类Job在实例化新对象时创建和标识:

  public Job() {
    UUID guid = UUID.randomUUID();
    id = guid.toString();
    title = "Random String";
  }

存储库目前只是一个存根:

@Repository
public class DemoJobRepository implements ReactiveRepository<Job> {
   private static Logger logger = LoggerFactory.getLogger(DemoJobRepository.class);
   private final List<Job> jobs = Lists.newArrayList();

@Override
public Mono<Void> create(Publisher<Job> jobStream) {
    return Flux.from(jobStream).doOnNext(jobs::add).then();
}

@Override
public Flux<Job> getAll() {
    return Flux.fromIterable(jobs);
}

@Override
public Mono<Job> findById(String id) {
    return null;
}
}

我没有看到客户端尝试发送请求正文。我们在客户端上调用了block 以获取结果,我看到客户端发送了请求,但是服务器端点总是看到一个空通量。请,非常感谢任何帮助。

【问题讨论】:

  • 据我了解,我不应该“破坏响应式管道并解耦请求的读取和响应的写入;很可能在您的控制器有机会读取之前,HTTP 交换可能会关闭整个请求。调用 subscribe 就是这样做的。你是说在存储库中调用subscribe 吗?
  • 我也使用 application/stream+json 的内容类型,因为其目的是通过连接流式传输数据,而不是发出许多单独的请求
  • 我不确定你是否理解我的意图。我的问题的第二个问题是:有效负载是 Job 对象的通量,内容类型是 application/stream+json 因此我不打算创建多个请求,而是将有效负载流式传输直到完成。跨度>
  • 您将一个对象发送到服务器。流媒体完全没有区别。流式传输 JSON 数据意味着单独发送对象而不是一次发送所有对象,这样可以减少内存消耗。请求没有区别。

标签: java reactive-programming spring-webflux project-reactor reactive


【解决方案1】:

对于响应式类型,nothing happens until you subscribe - 构建响应式管道不会执行它应该执行的操作,只有订阅它才会启动流程。

有几种订阅方式:

  • 调用任何subscribe 变体。其中许多将 lambdas 作为参数,在处理完成或以错误结束时执行。使用空变量有点冒险,因为它只是启动执行,但你没有得到任何回调。从技术上讲,没有什么在等待它,因此 JVM 可以在处理完成之前退出

  • 调用任何block/collect 方法。这不仅订阅而且返回预期值。

    这两种选择都不应该在返回反应类型的方法中完成,否则这将导致您的应用程序出现严重问题。

【讨论】:

  • 没有。调用 retrieve 确实会发送请求并请求响应正文 - 但由于它返回的是反应类型,因此在订阅时间之前什么都不会发生。
猜你喜欢
  • 2011-05-21
  • 1970-01-01
  • 2021-07-01
  • 1970-01-01
  • 2012-01-30
  • 2017-09-02
  • 2018-05-12
  • 2011-01-26
相关资源
最近更新 更多