为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

心有法竹 2023-09-13 16:56:51
我正在使用 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>?
查看完整描述

2 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

这里有两件事在起作用:

  • 事实上,您只能订阅(即读取)请求正文一次

  • 从请求中获取表单数据需要读取并解析它

在 Spring Boot 2.0.x-2.1.x 中,HiddenHttpMethodFilter默认启用。此过滤器对于在 HTML 表单中使用浏览器本身不支持的 HTTP 方法(例如“DELETE”)非常有用。如果传入请求属于该类型,则此过滤器需要解析表单数据。

可以说,这种用例越来越少见,并且从 Spring Boot 2.2 开始默认被禁用。

现在,在您的示例中,读取和解析传入请求将不起作用,因为它已被过滤器解析。禁用过滤器可以解决该问题。

但解决这个问题的更好方法是使用专用方法request.formData(),它将解析并缓存结果(如果多次调用,则返回已解析的数据)。


查看完整回答
反对 回复 2023-09-13
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

每当您等待表单数据时,您应该使用

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

我已经测试过,这种和平的代码适用于这一更改。


查看完整回答
反对 回复 2023-09-13
  • 2 回答
  • 0 关注
  • 59 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信