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:
问题原因
- WebClient注入失败:配置类仅声明了
WebClient.Builder的Bean,但直接注入WebClient实例,Spring容器中不存在该类型的Bean,导致webClient变量为null。调用webClient.method()时触发空指针异常,进而导致返回的Mono为null,触发日志中的错误。 - 违背响应式编程原则:使用
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
相关产品推荐
相关产品推荐

