Spring WebClient全局配置404返回Optional.empty()报错求解
问题原因
你在ExchangeFilterFunction的响应处理器中直接返回Mono.empty()是不合法的。WebClient的响应处理链要求必须要么输出一个有效的ClientResponse实例,要么抛出异常;返回空Mono会让底层客户端认为响应未正常完成,从而触发IllegalStateException。
解决方案
最简洁的方式是使用WebClient原生提供的defaultStatusHandler方法,全局配置404状态的处理逻辑,完全匹配你单独调用时的效果:
return WebClient.builder() .defaultStatusHandler( HttpStatus.NOT_FOUND::equals, clientResponse -> { // 必须消费404响应的body,避免连接资源泄漏 return clientResponse.bodyToMono(Void.class).then(Mono.empty()); } ) .build();
逻辑说明
defaultStatusHandler第一个参数指定要拦截的状态码(这里精准匹配404)- 第二个参数是处理逻辑:先通过
bodyToMono(Void.class)消费掉响应体(防止连接资源泄漏),再返回Mono.empty()。后续调用bodyToMono(User.class)时会得到空Mono,最终blockOptional()会返回Optional.empty(),和你单独实现的逻辑完全一致。
备选方案(基于ExchangeFilterFunction)
如果一定要用ExchangeFilterFunction实现,不能直接返回空Mono,需要先消费响应体再抛出异常,之后全局捕获该异常返回空Mono:
Function<ClientResponse, Mono<ClientResponse>> responseProcessor = clientResponse -> { HttpStatusCode status = clientResponse.statusCode(); if (HttpStatus.NOT_FOUND.equals(status)) { // 消费响应体后抛出404异常 return clientResponse.bodyToMono(Void.class) .then(Mono.error(new WebClientResponseException( status.value(), status.getReasonPhrase(), clientResponse.headers().asHttpHeaders(), null, null, null ))); } if (status.is4xxClientError() || status.is5xxServerError()) { return clientResponse.createError(); } return Mono.just(clientResponse); }; return WebClient.builder() .filter(ExchangeFilterFunction.ofResponseProcessor(responseProcessor)) .build();
调用时(或全局添加onErrorResume):
return webClient.get() .uri(buildUrl(username)) .retrieve() .bodyToMono(User.class) .onErrorResume(WebClientResponseException.class, e -> HttpStatus.NOT_FOUND.equals(e.getStatusCode()) ? Mono.empty() : Mono.error(e) ) .blockOptional();
显然第一种defaultStatusHandler的方式更简洁,无需在每个调用中重复编写异常处理逻辑。
内容的提问来源于stack exchange,提问作者gmode
相关产品推荐
相关产品推荐

