使用WebClient发送POST请求拉取外部API客户数据无返回问题咨询
问题排查及解决方案
核心错误点
- URL格式错误:示例中的请求URI写为
https//:anyurl.com,不符合HTTP URL规范,正确格式应为https://anyurl.com,冒号应在//之前。 - 请求体格式不匹配:接口要求提交JSON格式请求体,但现有代码使用
BodyInserters.fromFormData()提交表单数据,即使手动指定了application/json的Content-Type,实际提交的依然是x-www-form-urlencoded格式的内容,和接口要求不符。 - 未触发请求执行及响应解析:WebClient属于响应式编程组件,
retrieve()方法仅构造了请求描述符,并未实际触发请求执行,也未对返回结果做反序列化处理,直接打印ResponseSpec对象只能拿到对象的内存地址,无法得到接口返回数据。 - 实体类字段类型不匹配:接口返回的
data.id为字符串类型,但Clients类中定义的id为Long类型,若接口返回非数字格式id会触发反序列化失败;同时date字段接口返回为字符串,使用Timestamp接收需要匹配对应的日期格式,否则也会解析失败。
修复后的完整代码
请求代码
import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.sql.Timestamp; import java.util.List; public class Main { public static void main(String[] args) { WebClient client = WebClient.create(); // 构造JSON请求体对象 RequestDTO request = new RequestDTO(); request.setCommand("getClients"); ClientList result = client.post() // 修正URL格式 .uri("https://anyurl.com") .header("token", "myToken") .accept(org.springframework.http.MediaType.APPLICATION_JSON) // 直接传入对象,WebClient会自动序列化为JSON .bodyValue(request) .retrieve() // 新增异常捕获,方便排查请求错误 .onStatus(httpStatus -> !httpStatus.is2xxSuccessful(), clientResponse -> clientResponse.bodyToMono(String.class) .map(errorMsg -> new RuntimeException("接口请求失败,状态码:" + clientResponse.statusCode() + ",错误信息:" + errorMsg)) ) // 将响应反序列化为对应实体类 .bodyToMono(ClientList.class) // 阻塞等待请求执行完成拿到返回结果,生产环境非主程序场景建议改用subscribe订阅异步处理 .block(); // 打印返回结果 System.out.println("接口返回可用状态:" + result.getAvailable()); System.out.println("客户数据条数:" + result.getData().size()); result.getData().forEach(client -> System.out.println("客户ID:" + client.getId() + ",客户名称:" + client.getName())); } // 新增请求体DTO static class RequestDTO { private String command; public String getCommand() {return command;} public void setCommand(String command) {this.command = command;} } }
修正后的实体类
import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.util.List; class ClientList { private Boolean available; private List<Clients> data; // getter setter public Boolean getAvailable() {return available;} public void setAvailable(Boolean available) {this.available = available;} public List<Clients> getData() {return data;} public void setData(List<Clients> data) {this.data = data;} } @Document(collection = "clients") class Clients { @Id // 若确认接口返回id为纯数字可改回Long类型 private String id; private String name; // 若日期格式固定可匹配对应序列化规则改为Timestamp类型,否则先用String接收再手动转换 private String date; // getter setter public String getId() {return id;} public void setId(String id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} public String getDate() {return date;} public void setDate(String date) {this.date = date;} }
额外排查建议
如果修改后依然无法正常返回,可先用Postman等工具模拟请求,确认token权限、网络连通性、接口本身可用性,排除外部因素影响。
内容的提问来源于stack exchange,提问作者AlexWhite
相关产品推荐
相关产品推荐

