Spring Cloud Gateway post过滤器中发起HTTP请求的实现问题
现有实现的问题
- 类型不匹配错误:
Mono.fromRunnable()接收的是无返回值的Runnable接口实现,你在代码块中返回了responsePostHandler.flatMap(...)对应的Mono对象,直接触发了「Void methods cannot return a value」的编译报错。 - 异步逻辑未订阅问题:就算你去掉return语句,WebClient发起请求返回的Mono没有被加入响应式流的执行链,也没有被主动订阅,最终请求不会真正触发,只能看到日志打印,不会实际发起HTTP调用。
- 代码逻辑错误:
postHandlerResponse.bodyToMono(void.class)转换后得到的是Mono<Void>,你后续用postHandlerBody.statusCode根本拿不到状态码,状态码是postHandlerResponse的属性,不属于响应体。
正确实现方式
把chain.filter(exchange).then(...)中的包裹逻辑从Mono.fromRunnable替换为Mono.defer,让post阶段的异步HTTP请求能被正确加入响应式执行链,被订阅执行,参考代码如下:
return chain.filter(exchange).then(Mono.defer(() -> { LOGGER.info("Postfilter Begins"); ServerHttpResponse response = exchange.getResponse(); // 只有响应成功才执行post调用 if(response.getStatusCode().is2xxSuccessful()) { WebClient.RequestHeadersSpec requestPostHandler = webClientPostHandler.post() .uri("/xyzPostHandler") .header("Header key","value") .bodyValue("req body...."); LOGGER.info("Going to call postHandler"); return requestPostHandler.exchange() .flatMap(postHandlerResponse -> { // 直接从ClientResponse拿状态码 if (!postHandlerResponse.statusCode().equals(HttpStatus.OK)) { return this.handleExceptionCases(exchange, postHandlerResponse.statusCode().toString(), postHandlerResponse.statusCode()); } // 不需要响应体就直接返回空完成信号 return postHandlerResponse.releaseBody(); }); } // 不符合执行条件直接返回空完成信号 return Mono.empty(); }));
如果你的post调用不需要影响主流程的返回结果(哪怕post调用失败也正常返回业务接口的响应),可以在WebClient调用后加.subscribe(),把它变成异步后台任务,不需要串入主流程。
内容的提问来源于stack exchange,提问作者Sarthak M. Das
相关产品推荐
相关产品推荐

