You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Spring 5 WebClient处理服务器无响应及相关异常?

处理WebClient无响应/UnknownHostException场景的方案

WebClient的retrieve()方法仅处理HTTP响应状态码(4xx/5xx)的错误,而服务器宕机、URL错误这类网络级异常会以WebClientRequestException的形式抛出(内部包裹UnknownHostException),需要通过Reactor流的错误处理操作符来捕获处理,以下是两种可行方案:

1. 单个请求级别的异常处理

在请求链的末尾添加onErrorResume操作符,精准捕获WebClientRequestException并判断底层异常类型:

webClient
    .get()
    .uri("/api/something")
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError, errorHandlerFor4xx)
    .onStatus(HttpStatus::is5xxServerError, errorHandlerFor5xx)
    .bodyToMono(SomeStuff.class)
    .onErrorResume(WebClientRequestException.class, ex -> {
        // 判断是否为目标服务器不可达/URL错误
        if (ex.getCause() instanceof UnknownHostException) {
            // 此处可根据业务需求处理:比如返回默认对象、抛出自定义业务异常
            // 示例1:抛出自定义异常
            return Mono.error(new CustomServerUnavailableException("目标服务器不可达或URL配置错误", ex));
            // 示例2:返回默认数据
            // return Mono.just(new SomeStuff());
        }
        // 其他类型的WebClientRequestException,继续抛出或另行处理
        return Mono.error(ex);
    });

2. 全局配置级别的统一处理

如果希望所有WebClient请求都统一处理这类异常,可以通过添加exchangeFilterFunction实现全局拦截:

// 构建全局异常处理的过滤器
ExchangeFilterFunction unreachableServerFilter = (request, next) -> next.exchange(request)
    .onErrorResume(WebClientRequestException.class, ex -> {
        if (ex.getCause() instanceof UnknownHostException) {
            // 返回自定义的错误响应,让后续的retrieve()流程可以通过onStatus处理
            return Mono.just(ClientResponse.create(HttpStatus.SERVICE_UNAVAILABLE)
                .header("Content-Type", "application/json")
                .body("{\"code\":\"SERVER_UNREACHABLE\",\"msg\":\"目标服务器不可达\"}")
                .build());
        }
        return Mono.error(ex);
    });

// 构建WebClient时绑定全局过滤器
WebClient webClient = WebClient.builder()
    .baseUrl(someServerUrl)
    .filter(unreachableServerFilter)
    .build();

额外优化:配置超时时间

为了避免请求因服务器无响应一直阻塞,建议配置连接超时和读取超时:

// 配置Reactor HttpClient的超时参数
HttpClient httpClient = HttpClient.create()
    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) // 连接超时5秒
    .responseTimeout(Duration.ofSeconds(10)); // 读取超时10秒

WebClient webClient = WebClient.builder()
    .baseUrl(someServerUrl)
    .clientConnector(new ReactorClientHttpConnector(httpClient))
    .build();

超时异常同样可以通过onErrorResume捕获处理,判断异常类型为TimeoutException即可。


内容的提问来源于stack exchange,提问作者Ivan dal Bosco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:31:03