Java 将流媒体流量的WebClient Post拆分为JSON数组

Java 将流媒体流量的WebClient Post拆分为JSON数组,java,spring-webflux,project-reactor,reactive-streams,Java,Spring Webflux,Project Reactor,Reactive Streams,我使用的是第三方REST控制器,它接受JSON对象数组并返回单个对象响应。当我使用有限的Flux从WebClient发布时,代码会工作(我假设,因为Flux完成了) 然而,当流量可能是无限的时,我该怎么做 在数组块中发布 根据发布的阵列捕获响应 停止流量的传输 这是我的豆子 public class Car implements Serializable { Long id; public Car() {} public Car(Long id) { this.id

我使用的是第三方REST控制器,它接受JSON对象数组并返回单个对象响应。当我使用有限的
Flux
从WebClient发布时,代码会工作(我假设,因为
Flux
完成了)

然而,当
流量
可能是无限的时,我该怎么做

  • 在数组块中发布
  • 根据发布的阵列捕获响应
  • 停止
    流量的传输
  • 这是我的豆子

    public class Car implements Serializable {
    
        Long id;
    
        public Car() {}
        public Car(Long id) { this.id = id; }
        public Long getId() {return id; }
        public void setId(Long id) { this.id = id; }
    }
    
    这就是我假设第三方客户机的样子

    @RestController
    public class ThirdPartyServer {
    
        @PostMapping("/cars")
        public CarResponse doCars(@RequestBody List<Car> cars) {
            System.err.println("Got " + cars);
            return new CarResponse("OK");
        }
    }
    
  • 如何在数组块中发布
  • 使用的一种变体将主通量拆分为窗口通量,然后使用窗口通量通过
    .flatMap

    flux1=Flux.interval(持续时间为250毫秒)。map(i->newcar(i));
    WebClient客户端=WebClient.create(“http://localhost:8080");
    一次性使用=flux1
    // 1
    .窗口(5)
    .flatMap(windowedFlux->client
    .post()
    .uri(“/cars”)
    .contentType(MediaType.APPLICATION_JSON)
    .车身(车窗助焊剂,汽车类)
    .exchange()
    // 2
    .doOnNext(response->System.out.println(response.statusCode()))
    .flatMap(响应->响应.bodytomino(…))
    .subscribe();
    睡眠(10000);
    // 3
    一次性的,一次性的;
    
  • 如何捕获每个已发布阵列的响应
  • 您可以在
    .exchange()
    之后通过运算符分析响应

    在我提供的示例中,可以在
    doOnNext
    操作符中看到响应,但您可以使用对
    onNext
    信号进行操作的任何操作符,例如
    map
    handle

    请确保完全阅读响应正文,以确保连接返回到池(请参阅)。在这里,我使用了
    .bodytomino
    ,但是任何
    .body
    .toEntity
    方法都可以

  • 停止通量的传输
  • 当您像以前那样使用
    subscribe
    方法时,可以使用返回的
    disposable.dispose()
    停止流

    或者,您可以从
    sendCars()
    方法返回流量,并将订阅和处理委托给调用者


    请注意,在我提供的示例中,我只是使用
    Thread.sleep()
    来模拟等待。在实际的应用程序中,您应该使用更高级的工具,并避免两周内第二次来救我!我有一个相当开放的问题要问你;你是怎么得出这个答案的?我已经多次阅读了
    Flux
    WebClient
    API文档,并通过谷歌搜索了许多示例,但我从未接近在
    flatMap
    中使用
    WebClient
    。我假设所有将流分解成数组的
    流量
    魔法都会发生在
    .body()
    方法中!很高兴我能帮忙!
    WebClient
    exchange()
    方法仅表示一个请求。为了识别发送该请求的JSON数组的“末端”,主体(…)
    会完全读取提供给它的
    流量(这意味着它必须在请求完成之前完成)。因此,我意识到需要将输入
    Flux
    分解成卡盘(每个请求一个块)。将
    通量
    分解成块的一种方法是
    窗口(…)
    方法。谢谢,这应该可以帮助我解决未来的问题。菲尔,你可能需要修改答案。在运行解决方案时,由于响应负载未被读取,http连接未被释放,因此在几次迭代后,发布将停止,从而清空池。您需要在exchange()之后创建flatMap()。请参阅第2.3节末尾的评论,谢谢。我已经更新了答案,以显示阅读答案的一种可能方式(多种方式中的一种)。
    @Component
    public class MyCarClient {
    
        public void sendCars() {
    
    //      Flux<Car> flux1 = Flux.interval(Duration.ofMillis(250)).map(i -> new Car(i));
            Flux<Car> flux2 = Flux.range(1, 10).map(i -> new Car((long) i));
    
            WebClient client = WebClient.create("http://localhost:8080");
            client
                .post()
                .uri("/cars")
                .contentType(MediaType.APPLICATION_JSON)
                .body(flux2, Car.class) 
    //          .body(flux1.take(5).collectList(), new ParameterizedTypeReference<List<Car>>() {})
                .exchange()
                .subscribe(r -> System.err.println(r.statusCode()));
        }
    }