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

SpringCloud WebClient调用微服务API时URI识别异常(400错误)

WebClient调用API时URI格式错误(缺失http后双斜杠)导致400 Bad Request

问题现象

使用WebClient调用其他微服务API时抛出400错误,错误日志显示请求URI为http:/localhost:8082/Checkuser/252,缺失了http后的第二个斜杠,导致URI格式非法,请求失败。

错误日志详情

2023-01-23T17:10:17.261+08:00 ERROR 114017 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from UNKNOWN ] with root cause

org.springframework.web.reactive.function.client.WebClientResponseException$BadRequest: 400 Bad Request from UNKNOWN 
    at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:309) ~[spring-webflux-6.0.3.jar:6.0.3]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ 400 BAD_REQUEST from GET http:/localhost:8082/Checkuser/252 [DefaultWebClient]
Original Stack Trace:
        at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:309) ~[spring-webflux-6.0.3.jar:6.0.3]
        at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException$1(DefaultClientResponse.java:213) ~[spring-webflux-6.0.3.jar:6.0.3]
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onNext(FluxOnErrorReturn.java:162) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:122) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2071) ~[reactor-core-3.5.1.jar:3.5.1]
        at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145) ~[reactor-core-3.5.1.jar:3.5.1]
        at 

业务代码

Boolean result=webClientBuilder.build().get()
                .uri(uriBuilder -> uriBuilder
                        .path("http://localhost:8082/Checkuser/{id}")//"http://localhost:8082/Checkuser/{id}")
                        .build(252))
                        .retrieve()
                                .bodyToMono(Boolean.class)
                                        .block(); //make syn request

if(Boolean.FALSE.equals(result)){
   throw new IllegalAccessException("User score to low");

配置类代码

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;

@Configuration
public class webclientconfig {
    @Bean
    public WebClient webClient(){
        return WebClient.builder().build();
    }
    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder(){
        return WebClient.builder();
    }
}

问题原因与解决方法

原因

错误地使用uriBuilder.path()方法拼接包含协议、主机的完整URL,path()仅用于设置URI的路径部分,它会对传入字符串做规范化处理,导致http://被错误解析为http:/。

正确写法

有两种可行的修正方式:

方式1:直接传入完整URL到uri()

无需通过UriBuilder构建,直接将完整URL及参数传入uri()方法:

Boolean result = webClientBuilder.build().get()
        .uri("http://localhost:8082/Checkuser/{id}", 252)
        .retrieve()
        .bodyToMono(Boolean.class)
        .block();

方式2:通过UriBuilder分部分构建URI

如果需要使用UriBuilder,应分别设置协议、主机、端口和路径:

Boolean result = webClientBuilder.build().get()
        .uri(uriBuilder -> uriBuilder
                .scheme("http")
                .host("localhost")
                .port(8082)
                .path("/Checkuser/{id}")
                .build(252))
        .retrieve()
        .bodyToMono(Boolean.class)
        .block();

额外优化建议

既然已经配置了@LoadBalanced的WebClient.Builder,若调用的是注册到服务中心的微服务,可直接用服务名代替具体主机地址:

// 假设微服务注册名为checkuser-service
Boolean result = webClientBuilder.build().get()
        .uri("http://checkuser-service/Checkuser/{id}", 252)
        .retrieve()
        .bodyToMono(Boolean.class)
        .block();

内容的提问来源于stack exchange,提问作者user20112858

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:40:28