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

Spring Cloud Gateway中WebClient使用遇NullPointerException问题求助

Spring Cloud Gateway中WebClient响应获取失败问题排查与解决

问题场景

在Spring Cloud Gateway中使用WebClient发起请求时无法获取响应,触发NullPointerException,核心代码及错误信息如下:

WebClient配置类

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }

}

业务请求代码

@Autowired
public WebClient webClient;

public Mono<Response> getResponse(......) {

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add(HttpHeaders.AUTHORIZATION, authHeader);

    MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
    requestBody.add(.....);

    Mono<Response> responseMono = webClient.method(HttpMethod.POST)
            .uri("some usrl")
            .headers(httpHeaders -> httpHeaders.addAll(headers))
            .body(BodyInserters.fromValue(requestBody))
            .retrieve()
            .bodyToMono(Response.class);

    Mono<Response> customObjMono = responseMono.map(customObject -> {
        Response customObj = new Response();
        customObj.setAccessToken(customObject.getAccessToken());
        return customObj;
    });

    return customObjMono;
}

错误的响应获取方式

Mono<Response> token = client.getResponse(........);
AtomicReference<Response> plainJavaObject = new AtomicReference<>();
token.subscribe(transformedToken -> {
    plainJavaObject.set(transformedToken);
});
Response token = plainJavaObject.get();

错误日志

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! null
2023-07-22 19:12:05.533 ERROR 2668 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [b59e780c-3]  500 Server Error for HTTP POST "/greeting"

java.lang.NullPointerException: The Mono returned by the supplier is null
    at java.base/java.util.Objects.requireNonNull(Objects.java:233) ~[na:na]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ HTTP POST "/greeting" [ExceptionHandlingWebHandler]
Original Stack Trace:

问题原因

  1. WebClient注入失败:配置类仅声明了WebClient.Builder的Bean,但直接注入WebClient实例,Spring容器中不存在该类型的Bean,导致webClient变量为null。调用webClient.method()时触发空指针异常,进而导致返回的Mono为null,触发日志中的错误。
  2. 违背响应式编程原则:使用AtomicReference配合subscribe()同步获取响应的方式错误。Reactor是异步非阻塞模型,subscribe()后立刻调用get()时,异步请求尚未完成,plainJavaObject仍为null,无法获取有效响应。

解决方案

1. 修复WebClient注入问题

修改配置类,直接声明WebClient类型的Bean:

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient() {
        return WebClient.builder().build();
    }

}

或者通过WebClient.Builder构建实例后注入:

@Autowired
private WebClient.Builder webClientBuilder;

private WebClient webClient;

@PostConstruct
public void init() {
    this.webClient = webClientBuilder.build();
}

2. 修正响应式调用逻辑

放弃阻塞式获取结果的方式,保持响应式流的连续性。例如在Gateway Filter中正确处理:

// 调整getResponse方法,直接返回响应式流
public Mono<Response> getResponse(...) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add(HttpHeaders.AUTHORIZATION, authHeader);

    MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
    requestBody.add(.....);

    // 修正URL拼写错误(原代码中为"some usrl")
    return webClient.method(HttpMethod.POST)
            .uri("your-actual-url")
            .headers(httpHeaders -> httpHeaders.addAll(headers))
            .body(BodyInserters.fromValue(requestBody))
            .retrieve()
            .bodyToMono(Response.class)
            .map(customObject -> {
                Response customObj = new Response();
                customObj.setAccessToken(customObject.getAccessToken());
                return customObj;
            });
}

// 在Gateway Filter中使用示例
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    return client.getResponse(...)
            .flatMap(response -> {
                // 将响应结果存入Exchange属性供后续使用
                exchange.getAttributes().put("ACCESS_TOKEN", response.getAccessToken());
                return chain.filter(exchange);
            })
            .onErrorResume(ex -> {
                // 异常处理:返回500错误
                exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
                return exchange.getResponse().setComplete();
            });
}

3. 额外注意事项

  • 修正原代码中URL的拼写错误("some usrl"改为实际有效的请求地址)。
  • 确保Response类具备正确的Jackson序列化/反序列化注解(如@Data、@JsonProperty等),避免响应解析失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:05:20