如何使WebClient捕获io.netty.ReadTimeoutException至指定catch块
解决WebClient无法直接捕获ReadTimeoutException的问题
问题原因
你通过Netty的ReadTimeoutHandler配置的超时属于底层Netty层面异常,会被Reactor客户端连接器捕获后包装为WebClientRequestException抛出,因此直接捕获ReadTimeoutException的代码块无法命中。
推荐解决方案:使用WebClient内置超时配置
替代手动添加ReadTimeoutHandler,直接通过WebClient依赖的HttpClient配置响应超时,超时发生时会直接抛出ReadTimeoutException,可被对应catch块捕获:
// 构建配置了读取超时的HttpClient HttpClient httpClient = HttpClient.create() .responseTimeout(Duration.ofSeconds(5)); // 设置5秒读取超时 // 初始化WebClient时传入该HttpClient WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build();
调用接口时即可直接捕获目标异常:
try { String response = webClient.get() .uri("/your-api-endpoint") .retrieve() .bodyToMono(String.class) .block(); // 同步调用示例,异步场景同理 } catch (ReadTimeoutException e) { // 直接处理读取超时逻辑 System.err.println("读取超时:" + e.getMessage()); } catch (WebClientRequestException e) { // 处理其他请求层面异常 System.err.println("请求异常:" + e.getMessage()); }
备选方案:解析WebClientRequestException的底层异常
如果必须保留ReadTimeoutHandler配置,可在捕获WebClientRequestException后,检查其异常链中的cause是否为ReadTimeoutException:
try { String response = webClient.get() .uri("/your-api-endpoint") .retrieve() .bodyToMono(String.class) .block(); } catch (ReadTimeoutException e) { // 理论上不会进入这里,除非异常未被包装 e.printStackTrace(); } catch (WebClientRequestException e) { Throwable rootCause = e.getCause(); if (rootCause instanceof ReadTimeoutException) { // 处理读取超时逻辑 System.err.println("读取超时:" + rootCause.getMessage()); } else { // 处理其他请求异常 System.err.println("请求异常:" + e.getMessage()); } }
说明
优先选择第一种方案,WebClient内置超时配置更贴合Reactor异步模型,无需手动处理Netty层面的异常包装,代码简洁直观。
内容的提问来源于stack exchange,提问作者CN1002
相关产品推荐
相关产品推荐

