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

Spring Webflux响应式链中如何在doOnNext里获取原始请求对象?

解决方案

方案一:通过flatMap关联请求与结果(推荐)

这种方式直接简洁,无需额外上下文传递,还能避免请求体重复解析的问题:

修改控制器代码:

@PostMapping("url")
public Mono<MyResponse> getMyResponse(@RequestBody Mono<MyRequest> myRequestMono) {
    // 缓存请求Mono,防止多次订阅导致请求体被重复解析
    Mono<MyRequest> cachedRequest = myRequestMono.cache();

    return cachedRequest.flatMap(request -> 
        urlService.getUrl(Mono.just(request))
            .doOnNext(url -> {
                // 直接访问请求对象的目标字段,比如id
                System.out.println("Generated URL: Successfully for request ID: " + request.getId());
            })
            .map(dto -> MyResponse.builder().url(dto).build())
    )
    .doOnError(e -> System.out.println("Error: " + e.getMessage()));
}

说明:

  • cache()方法用于缓存请求Mono,避免因控制器和服务的多次订阅触发请求体重复解析。
  • 通过flatMap将原始请求对象与服务返回结果绑定,在doOnNext中可以直接访问请求的所有字段,完全不需要修改服务类逻辑。

方案二:正确使用Reactor上下文(适合跨组件传递场景)

如果需要在多个组件间共享请求对象,可通过Reactor上下文传递,但要避免重复读取请求体:

修改控制器代码:

@PostMapping("url")
public Mono<MyResponse> getMyResponse(@RequestBody Mono<MyRequest> myRequestMono) {
    return myRequestMono
        .flatMap(request -> 
            urlService.getUrl(Mono.just(request))
                .map(url -> MyResponse.builder().url(url).build())
                // 将请求对象存入上下文
                .contextWrite(ctx -> ctx.put("MY_REQUEST", request))
        )
        .transformDeferredContextual((responseMono, contextView) -> 
            responseMono.doOnNext(response -> {
                // 从上下文中取出请求对象
                MyRequest request = contextView.get("MY_REQUEST");
                System.out.println("Generated URL: Successfully for request ID: " + request.getId());
            })
        )
        .doOnError(e -> System.out.println("Error: " + e.getMessage()));
}

说明:

  • 直接在控制器中将请求放入上下文,避免了WebFilter重复读取请求体导致控制器无法获取数据的问题。
  • transformDeferredContextual用于延迟访问上下文,确保上下文已被正确填充后再读取。

你之前的上下文方案失败原因

你尝试的WebFilter方案存在核心问题:Spring Webflux中请求体是Flux<DataBuffer>,只能被订阅/读取一次。如果WebFilter先解析了请求体,控制器的@RequestBody将无法再读取到数据,直接导致请求失败,因此这种方式不适用你的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:40:32