Spring Reactive Web Applications POST请求正文丢失

时间:2018-08-02 20:38:31

标签: java spring spring-webflux project-reactor

我正在做一个小型测试项目,以检查Spring Reactive Web Applications如何与MongoDB一起实际工作。

我遵循https://docs.spring.io/spring/docs/5.0.0.M4/spring-framework-reference/html/web-reactive.html中的手册

它指出我可以在控制器中处理POST请求,例如:

@PostMapping("/person")
    Mono<Void> create(@RequestBody Publisher<Person> personStream) {
        return this.repository.save(personStream).then();
    }

尽管这似乎行不通。我在这里实现的控制器:

https://github.com/pavelmorozov/reactor-poc/blob/master/src/main/java/com/springreactive/poc/controller/BanquetHallController.java

它只有一个POST映射,非常简单:

@PostMapping("/BanquetHall")
    Mono<Void> create(@RequestBody Publisher<BanquetHall> banquetHallStream) {
        return banquetHallRepository.insert(banquetHallStream).then();
    }

每次发布​​带有curl的POST时都会调用它:

curl -v -XPOST -H "Content-type: application/json" -d '{"name":"BH22"}' 'http://localhost:8080/BanquetHall'
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /BanquetHall HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
> Content-type: application/json
> Content-Length: 15
> 
* upload completely sent off: 15 out of 15 bytes
< HTTP/1.1 200 OK
< content-length: 0
< 
* Connection #0 to host localhost left intact

我看到mongodb中存储了新对象,但是它们不包含数据。为了调试,我建立了一个简单的订阅服务器,以查看实际作为请求主体传递给控制器​​的数据:

Subscriber s = new Subscriber() {
    @Override
    public void onSubscribe(Subscription s) {
        logger.info("Argument: "+s.toString());
    }
    @Override
    public void onNext(Object t) {
        logger.info("Argument: "+t.toString());

    }
    @Override
    public void onError(Throwable t) {
        logger.info("Argument: "+t.toString());
    }
    @Override
    public void onComplete() {
        logger.info("Complete! ");
    }
};
banquetHallStream.subscribe(s);

,现在我看到订阅onError方法被调用之后。 Throwable状态主体丢失:

Request Error 400

Here error string:
Request body is missing: reactor.core.publisher.Mono<java.lang.Void> com.springreactive.poc.controller.BanquetHallController.create(org.reactivestreams.Publisher<com.springreactive.poc.domain.BanquetHall>)

为什么请求正文为空?

也要知道:随着我对所有这些反应性内容的了解,是否可以通过一种无需手动实现订户的方法来更好地调试Publisher / Subscriber?

更新,我更新了POST处理程序方法说明,并将请求正文作为String对象传递:

Mono<Void> create(@RequestBody String banquetHallStream)

然后这不是“反应式”,对吗?字符串不是被动的,因为发布者应该...

1 个答案:

答案 0 :(得分:0)

我遇到了完全相同的问题,并且可以通过在方法上放置@ResponseStatus来解决此问题。下面是方法控制器的外观:

@ResponseStatus(HttpStatus.CREATED)
@PostMapping(value = "/bulk", consumes = APPLICATION_STREAM_JSON_VALUE)
public Mono<Void> bulkInsert(@RequestBody Flux<Quote> quotes) {
    return quoteReactiveRepository.insert(quotes).then();
}

我正在使用WebClient向该端点发出请求:

webClient.post()
        .uri("/quotes/bulk")
        .contentType(MediaType.APPLICATION_STREAM_JSON)
        .body(flux(), Quote.class)
        .retrieve()
        .bodyToMono(Void.class).block();

经过测试:org.springframework.boot:spring-boot-starter-webflux:2.1.0.RELEASE