Spring Boot WebClient空响应体触发IllegalStateException异常咨询
异常根因
这个报错是你的onStatus处理逻辑存在疏漏导致的,和WireMock测试用例编写无关。
- 当5xx响应携带有效响应体时,
clientResponse.bodyToMono(String.class)会正常发射响应内容,后续flatMap执行抛出MyCustomServiceException,流按预期终止,不会触发额外操作。 - 当5xx响应无响应体时,
bodyToMono(String.class)会返回空Mono,此时你写的flatMap不会被触发,onStatus回调最终返回空Mono,等价于告知WebClient该状态码未被判定为错误、流可以继续执行。后续执行到toEntity(String.class)时,WebClient会尝试第二次订阅响应连接读取内容,而Netty的客户端响应流仅允许被订阅一次,就会抛出java.lang.IllegalStateException: Only one connection receive subscriber allowed。
修复代码
只需要保证onStatus回调无论是否存在响应体,最终都返回发射错误的Mono即可,不要让空Mono流到后续环节:
webClient.get() .uri(targetServiceUri) .retrieve() .onStatus(HttpStatus::is5xxServerError, clientResponse -> clientResponse.bodyToMono(String.class) // 空响应体时使用默认错误提示 .defaultIfEmpty("service returned status " + clientResponse.rawStatusCode()) .flatMap(errorContent -> Mono.error(new MyCustomServiceException(errorContent))) ) .toEntity(String.class) .block();
验证说明
修复后两个场景都符合预期:
- 有响应体的5xx错误:直接取响应体内容作为异常信息,第一个测试用例正常通过
- 无响应体的5xx错误:自动使用定义的默认提示抛出自定义异常,不会触发二次订阅,第二个测试用例正常通过
内容的提问来源于stack exchange,提问作者Vincent F
相关产品推荐
相关产品推荐

