Spring WebClient路由4xx/5xx错误响应及HTTP状态码问题
解决ProxyApp转发BusinessApp错误状态码被重置为200的问题
问题根源
你的代码里有两处直接导致错误状态码被重置的问题:
.onStatus(HttpStatus::isError, clientResponse -> Mono.empty()):这行代码把BusinessApp返回的错误状态码响应直接转换成空的Mono,相当于把错误“吞掉”,WebClient不会抛出异常,会继续走正常流程- 方法上的
@ResponseStatus(HttpStatus.OK):硬编码了响应状态为200,不管实际调用BusinessApp的结果是什么,最终都会返回200
解决方案
要实现完整转发响应体和状态码,需要做以下调整:
- 移除错误状态码的空Mono处理,改为直接捕获并处理所有状态的响应
- 把方法返回类型从
String改为ResponseEntity<String>,支持动态设置HTTP状态码 - 用
exchangeToMono替代retrieve(),直接访问完整的客户端响应信息
修改后的代码
@Operation(summary = "Some desc") @PostMapping(value = "/", consumes = {MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_JSON_VALUE}) @ApiResponse(responseCode = "200", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = User.class)) }) // 移除硬编码的@ResponseStatus,让ResponseEntity动态决定状态码 public ResponseEntity<String> someMethod() { // skipped return webClient.post() .uri(url) .contentType(MediaType.APPLICATION_JSON) .bodyValue(request) .exchangeToMono(clientResponse -> { // 统一处理所有状态码:正常响应和错误响应 return clientResponse.bodyToMono(String.class) .map(body -> ResponseEntity.status(clientResponse.statusCode()).body(body)); }) .onErrorMap(WebClientRequestException.class, ex -> new RestApiUnavailableException(ex,"some msg")) .block(); }
代码说明
exchangeToMono:替代retrieve()后可以直接获取完整的ClientResponse,包括状态码和响应体,不管是成功还是错误状态都能处理- 动态状态码:通过
clientResponse.statusCode()获取BusinessApp返回的原始状态码,再将响应体封装到ResponseEntity中返回 - 移除错误吞逻辑:不再忽略错误状态码,确保所有响应状态都能原样转发
补充:Swagger注解优化
如果需要让Swagger生成的客户端包含错误状态码的定义,可以补充对应的@ApiResponse:
@ApiResponse(responseCode = "400", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)) }) @ApiResponse(responseCode = "500", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)) })
内容的提问来源于stack exchange,提问作者sasynkamil
相关产品推荐
相关产品推荐

