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
相关产品推荐
相关产品推荐

