如何在 Spring 反应式处理函数中提取请求主体?

我正在使用 Spring Web Flux 实现一个处理程序函数,并希望提取 POST-Body 的值x-www-form-urlencoded。


public Mono<ServerResponse> handle(ServerRequest incomingHttpRequest) {

    Mono<MultiValueMap<String, String>> formData = incomingHttpRequest.body(BodyExtractors.toFormData());

    return formData

            .doOnEach(signal -> {LOG.info("EACH: " + signal.getType());})

            .doOnSubscribe(x -> {LOG.info("SUBSCRIBED");})

            .doOnNext(next -> {LOG.info("NEXT: " + next);})

            .doOnError(x -> {LOG.info("ERROR: " + x.getMessage());})

            .doOnSuccess(x -> {LOG.info("SUCCESS: " + x);})

            .flatMap(multiValueMap -> ServerResponse

                .badRequest()

                .body(BodyInserters.fromObject(

                    "searchTerm: " + multiValueMap.getFirst("searchTerm")

                ))

            );

}

处理程序添加到路由器中,如下所示:


return RouterFunctions.route(RequestPredicates.POST("/mysearch"), searchHandler::handle);

                                                                              

我希望得到一个包含 searchTerm 的 BAD_REQUEST。但我得到的是 200。


对我来说,看起来生成的 Mono 已被订阅,然后成功完成。但formData从未收到值,因此从未进入flatMap(...)


我做错了什么映射Mono<MultiValueMap<String, String>>到 a Mono<ServerResponse>?


心有法竹
浏览 95回答 2
2回答

不负相思意

这里有两件事在起作用:事实上,您只能订阅(即读取)请求正文一次从请求中获取表单数据需要读取并解析它在 Spring Boot 2.0.x-2.1.x 中,HiddenHttpMethodFilter默认启用。此过滤器对于在 HTML 表单中使用浏览器本身不支持的 HTTP 方法(例如“DELETE”)非常有用。如果传入请求属于该类型,则此过滤器需要解析表单数据。可以说,这种用例越来越少见,并且从 Spring Boot 2.2 开始默认被禁用。现在,在您的示例中,读取和解析传入请求将不起作用,因为它已被过滤器解析。禁用过滤器可以解决该问题。但解决这个问题的更好方法是使用专用方法request.formData(),它将解析并缓存结果(如果多次调用,则返回已解析的数据)。

Cats萌萌

每当您等待表单数据时,您应该使用Mono<MultiValueMap<String, String>> formData = incomingHttpRequest.formData();我已经测试过,这种和平的代码适用于这一更改。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java