You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebFlux跨微服务发送Flux<Integer>遇400请求体缺失错误

问题描述

尝试通过POST请求从微服务A向微服务B发送Flux<Integer>,能命中B的端点,但收到400 BAD_REQUEST错误:

No request body for: public org.springframework.http.ResponseEntity<reactor.core.publisher.Mono<java.lang.Void>> com.example.registryservice.controller.RegistryController.createPackage(reactor.core.publisher.Flux<java.lang.Integer>)

已尝试给微服务B的/packages端点添加@ResponseStatus注解,问题仍未解决。


相关代码实现

微服务A代码

Flux<Integer> integerFlux = Flux.just(1,2,3,4,5);
WebClient.create("http://localhost:9002/registry")
            .post()
            .uri("/packages")
            .contentType(MediaType.APPLICATION_NDJSON)
            .body(integerFlux, Integer.class)
            .retrieve()
            .bodyToMono(Void.class)
            .subscribe(System.out::print);

微服务B代码

@PostMapping(value = "/packages", consumes = MediaType.APPLICATION_NDJSON_VALUE)
public ResponseEntity<Mono<Void>> createPackage(@RequestBody Flux<Integer> integerFlux) {
    integerFlux.subscribe(new Subscriber<>() {

        @Override
        public void onSubscribe(Subscription s) {
            System.out.println("onSubscribe Subscription: " + s);
        }

        @Override
        public void onNext(Integer t) {
            System.out.println("onNext Integer: " + t);
        }

        @Override
        public void onError(Throwable t) {
            System.out.println("onError Throwable: " + t);
        }

        @Override
        public void onComplete() {
            System.out.println("onComplete");

        }
    });
    return new ResponseEntity<>(HttpStatus.CREATED);
}

pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <version>0.0.1-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.4</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example.demo</groupId>
    <artifactId>action</artifactId>
    <name>action</name>
    <description>Action Spring Boot application</description>
    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

问题分析与解决方案

核心问题1:控制器返回值类型错误

当前控制器返回ResponseEntity<Mono<Void>>,不符合WebFlux的响应式编程规范。Spring WebFlux要求控制器返回响应式类型(如Mono/Flux)来管理异步流程,而不是把响应式类型包裹在ResponseEntity中。这种写法会导致框架错误解析请求体逻辑,触发"No request body"异常。

核心问题2:手动订阅Flux违反上下文管理

在控制器中直接调用integerFlux.subscribe()会脱离Spring WebFlux的上下文控制,导致请求体还未被完整处理就返回响应,同时订阅操作无法被框架正确追踪,进一步引发请求体解析异常。正确做法是通过响应式操作符处理流,让框架管理订阅生命周期。

修正后的微服务B代码

@PostMapping(value = "/packages", consumes = MediaType.APPLICATION_NDJSON_VALUE)
public Mono<ResponseEntity<Void>> createPackage(@RequestBody Flux<Integer> integerFlux) {
    return integerFlux
            .doOnNext(t -> System.out.println("onNext Integer: " + t))
            .doOnSubscribe(s -> System.out.println("onSubscribe Subscription: " + s))
            .doOnError(t -> System.out.println("onError Throwable: " + t))
            .doOnComplete(() -> System.out.println("onComplete"))
            .then(Mono.just(ResponseEntity.status(HttpStatus.CREATED).build()));
}

额外优化建议

  • 微服务A中,建议不要直接在代码内调用subscribe(),而是返回Mono让上层调用者处理订阅,避免异步操作脱离上下文。
  • 移除pom.xml中单独引入的spring-web依赖,spring-boot-starter-webflux已经包含该模块,重复引入可能导致依赖冲突。

内容的提问来源于stack exchange,提问作者Ronit Nath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:35:10