Spring Boot WebFlux中如何实现两个WebClient请求按顺序执行
Spring Boot WebFlux 双WebClient顺序执行解决方案
该问题的本质是响应式编程的声明式特性:独立定义的两个WebClient请求如果没有组装到同一条响应式流中,订阅后会异步并行执行,不会等待前序请求完成。你可以通过flatMap操作符串联两个请求逻辑,确保第一个请求完成、拿到映射后的POJO后,再触发第二个请求。
错误写法示例(会触发并行执行)
以下写法会导致第二个请求提前触发,拿到的账户数据为null:
// 错误:两个请求逻辑独立声明,无依赖关系 Mono<Account> accountReq = firstWebClient.get() .uri("/get/account") .retrieve() .bodyToMono(Account.class); // 第二个请求没有依赖第一个的执行结果,订阅后会直接触发 Mono<Result> secondReq = secondWebClient.post() .uri("/submit/data") .bodyValue(new Account()) // 此时第一个请求还没返回,拿不到实际数据 .retrieve() .bodyToMono(Result.class);
正确写法(顺序执行)
用flatMap操作符将两个请求组装为同一条响应式流:
public Mono<Result> runSequentialRequest() { return firstWebClient.get() .uri("https://first-api.com/account") .retrieve() // WebClient默认内置ObjectMapper,可直接反序列化为指定POJO,无需手动调用ObjectMapper .bodyToMono(Account.class) // 只有上一步拿到非空的Account对象后,才会触发第二个WebClient请求 .flatMap(account -> secondWebClient.post() .uri("https://second-api.com/submit") .bodyValue(account) .retrieve() .bodyToMono(Result.class)); }
如果需要手动调用ObjectMapper做自定义反序列化,可在中间增加map操作符处理:
public Mono<Result> runSequentialRequestWithCustomMapper() { return firstWebClient.get() .uri("https://first-api.com/account") .retrieve() .bodyToMono(String.class) // 手动反序列化,该步骤完成后才会进入下一步flatMap .map(rawResp -> objectMapper.readValue(rawResp, Account.class)) .flatMap(account -> secondWebClient.post() .uri("https://second-api.com/submit") .bodyValue(account) .retrieve() .bodyToMono(Result.class)); }
注意事项
- 全程不要调用
block()方法阻塞线程,会破坏响应式非阻塞特性,组装完成的Mono/Flux直接返回给Spring框架,由框架负责订阅执行即可。 - 如果第一个接口有概率返回空响应,可在
bodyToMono后增加switchIfEmpty(Mono.error(new IllegalArgumentException("未获取到有效账户数据")))主动抛出异常,避免非法参数传入第二个请求。 - 可分别在两个请求的
retrieve后增加onErrorResume等操作符自定义异常降级逻辑。
内容的提问来源于stack exchange,提问作者Ash
相关产品推荐
相关产品推荐

