WebClient如何使用ResponseEntity<Mono<String>>发起GET调用?
WebClient 实现GET请求提前获取响应头并行处理的方案
根据Spring WebFlux的官方特性说明:
使用
ResponseEntity<Mono<T>>或ResponseEntity<Flux<T>>结构处理响应时,客户端/服务端会在收到响应头、响应状态码后立刻触发对应逻辑,不需要等待整个响应体传输、解析完成;单值响应选择Mono作为响应体包装类型,多值/流式响应选择Flux即可。
针对「第一时间获取响应头,等待响应体过程中并行执行其他逻辑」的GET调用场景,具体实现方式如下:
核心实现逻辑
- 发起请求时不要直接将响应映射为目标实体类,先获取原生响应的包装结构,确保响应头返回后立刻进入处理分支
- 拿到响应头后,将无需依赖响应体的业务逻辑包装为异步任务,和响应体接收解析流程并行执行
- 阻塞型的并行处理逻辑必须指定独立调度线程池,避免阻塞WebFlux核心IO线程
完整代码示例
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import lombok.extern.slf4j.Slf4j; import lombok.Data; @Slf4j public class HeaderFirstGetClient { // 实际项目中可将WebClient注册为全局Bean统一配置超时、拦截器等参数 private static final WebClient WEB_CLIENT = WebClient.builder() .baseUrl("http://target-service-domain") .build(); /** * 带响应头提前处理的GET调用 * @return 解析完成的响应体实体 */ public Mono<ResponseDto> getWithParallelHeaderProcess() { return WEB_CLIENT.get() .uri("/api/target-endpoint") // 关键:exchangeToMono会在收到响应头后立刻触发回调,无需等待响应体 .exchangeToMono(clientResponse -> { // 此处已可同步读取响应状态、所有响应头 HttpStatus status = clientResponse.statusCode(); HttpHeaders headers = clientResponse.headers().asHttpHeaders(); String traceId = headers.getFirst("X-Trace-Id"); long contentLen = headers.getContentLength(); // 包装不依赖响应体的并行处理逻辑 Mono<Void> parallelTask = Mono.fromRunnable(() -> { // 此处写自定义并行逻辑:比如日志埋点、上下文初始化、异步通知等 log.info("提前获取响应头完成,traceId:{}, 响应状态:{}", traceId, status.value()); // 阻塞操作必须放在boundedElastic调度器执行,避免卡IO线程 try { Thread.sleep(150); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } log.info("响应头相关并行处理执行完成"); }).subscribeOn(Schedulers.boundedElastic()) .doOnError(e -> log.error("并行处理逻辑执行失败", e)); // 单独处理并行任务异常,避免影响主流程 // 异步接收解析响应体 Mono<ResponseDto> bodyMono = clientResponse.bodyToMono(ResponseDto.class); // 方案1:等待并行任务和响应体都完成后返回结果 return parallelTask.then(bodyMono); // 方案2:不需要等并行任务完成、直接返回响应体(放开下方注释即可) // parallelTask.subscribe(); // return bodyMono; }); } // 自定义响应体DTO @Data public static class ResponseDto { private Long id; private String content; } }
注意事项
- 如果调用的接口返回数组、SSE流式数据,把
bodyToMono替换为bodyToFlux即可,响应头提前读取、并行处理的逻辑完全不变 - 若选择不等待并行任务直接返回响应体,必须给并行任务单独配置异常处理逻辑,避免异常静默丢失
- 不要在
exchangeToMono的回调主线程里直接写阻塞逻辑,所有阻塞操作必须指定对应调度器
内容的提问来源于stack exchange,提问作者Sudip Subedi
相关产品推荐
相关产品推荐

