RestTemplate转WebClient后请求超时问题求助
问题排查与解决建议
1. 修正请求头的环境标识
原RestTemplate代码中HEADER_ENV设置的是it01,但WebClient里写成了blahblah,这会导致服务端无法识别请求环境,可能引发路由错误或处理阻塞,最终导致超时。
修改WebClient的头配置:
httpHeaders.add(Constants.HEADER_ENV, "it01"); // 替换原有的"blahblah"
2. 对齐请求体的序列化方式
原RestTemplate使用预先通过safeObjectMapper()序列化好的bodyString,但WebClient直接传入wlsMemoRequest,会使用WebClient默认的ObjectMapper序列化,若和原有序列化配置(如日期格式、字段命名策略)不一致,会导致服务端无法解析请求体,一直等待数据最终超时。
可以显式复用原有序列化逻辑:
.bodyValue(safeObjectMapper().writeValueAsString(wlsMemoRequest))
或者配置WebClient使用自定义ObjectMapper:
WebClient webClient = WebClient.builder() .codecs(configurer -> configurer.defaultCodecs().jackson2JsonEncoder( new Jackson2JsonEncoder(safeObjectMapper()) )) .defaultHeaders(httpHeaders -> { // 其他头配置 }) .build();
3. 确保Mono被订阅
WebClient是异步非阻塞的,返回的Mono<CreateWlsMemoResponse>只有在被订阅(调用subscribe()/block()等方法)时才会实际发送请求。如果代码中没有订阅操作,请求根本不会执行,表现为"超时"。
根据业务场景选择订阅方式:
- 同步阻塞(和RestTemplate行为一致):
CreateWlsMemoResponse response = createWlsMemoResponse.block();
- 异步处理:
createWlsMemoResponse.subscribe( response -> logger.info("响应结果: {}", response), error -> logger.error("请求失败", error) );
4. 统一超时配置
RestTemplate和WebClient默认超时配置不同,可显式设置WebClient超时匹配原有RestTemplate的行为:
WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector( HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) .responseTimeout(Duration.ofSeconds(10)) )) .defaultHeaders(httpHeaders -> { // 头配置 }) .build();
5. 完善状态码处理逻辑
原代码仅处理HttpStatus.OK,但服务端可能返回其他合法成功状态码(如201 Created),建议优化状态判断逻辑:
.exchangeToMono(response -> { if (response.statusCode().is2xxSuccessful()) { logger.info("获取正常响应"); return response.bodyToMono(CreateWlsMemoResponse.class); } else { return response.bodyToMono(String.class) .flatMap(errorBody -> { logger.error("请求失败,状态码: {}, 响应体: {}", response.statusCode(), errorBody); return Mono.error(new CreateMemoException("请求失败,状态码: " + response.statusCode())); }); } });
内容的提问来源于stack exchange,提问作者Derrick Zoleta
相关产品推荐
相关产品推荐

