Spring Boot WebClient添加onStatus后调用bodyToMono遇NPE求助
WebClient添加onStatus后调用bodyToMono触发空指针异常的解决办法
我在用Spring Boot WebClient发送POST请求时遇到问题:请求本身能正常执行,但添加onStatus处理HTTP错误码后,调用bodyToMono会抛出空指针异常(NPE);移除onStatus就能正常获取响应。我需要处理所有4xx、5xx错误,以及402、404、500、512这些具体错误码,原代码如下:
Employee createdEmployee = webClient.post() .uri("/employees") .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .body(Mono.just(empl), Employee.class) .retrieve() .onStatus(HttpStatus::isError, clientResponse -> { if (clientResponse.statusCode() == HttpStatus.resolve(402)) { return Mono.error(new Exception("402")); } log.error("Error endpoint with status code {}", clientResponse.statusCode()); if (clientResponse.statusCode() == HttpStatus.resolve(500)) { return Mono.error(new Exception("500")); } if (clientResponse.statusCode() == HttpStatus.resolve(512)) { return Mono.error(new Exception("512")); } return Mono.error(new Exception("Error while processing request")); }) .bodyToMono(Employee.class);
问题原因
触发NPE的核心是:当onStatus匹配到错误状态码时,你直接返回了Mono.error,但没有消费错误响应的body。WebClient要求必须读取完响应体才能完成请求生命周期,未消费的响应体会导致资源泄漏,进而引发空指针这类异常。
修正方案
修改onStatus的处理逻辑,在返回错误信号前,先读取并消费响应体。可以用bodyToMono(Void.class)快速丢弃响应体,也可以根据实际需求解析错误响应内容。
修正后的代码:
Employee createdEmployee = webClient.post() .uri("/employees") .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .body(Mono.just(empl), Employee.class) .retrieve() .onStatus(HttpStatus::isError, clientResponse -> { // 先消费响应体,避免资源泄漏和NPE return clientResponse.bodyToMono(Void.class) .then(Mono.defer(() -> { HttpStatus status = clientResponse.statusCode(); if (status == HttpStatus.PAYMENT_REQUIRED) { // 标准402对应的枚举值 return Mono.error(new Exception("402")); } else if (status == HttpStatus.NOT_FOUND) { // 404 return Mono.error(new Exception("404")); } else if (status == HttpStatus.INTERNAL_SERVER_ERROR) { // 500 return Mono.error(new Exception("500")); } else if (status == HttpStatus.resolve(512)) { // 512非标准状态码,用resolve return Mono.error(new Exception("512")); } log.error("Error endpoint with status code {}", status); return Mono.error(new Exception("Error while processing request")); })); }) .bodyToMono(Employee.class);
额外优化建议
- 优先使用
HttpStatus枚举值(比如HttpStatus.PAYMENT_REQUIRED),比resolve()更可靠,避免返回空值 - 自定义业务异常类代替通用
Exception,方便后续精准捕获和处理 - 如果服务端返回了结构化错误信息,可以把
bodyToMono(Void.class)改成解析错误DTO,将错误详情带到自定义异常中
内容的提问来源于stack exchange,提问作者Nesan Mano
相关产品推荐
相关产品推荐

