Spring Boot项目使用WebClient调用第三方接口详细教程

目录

一、简单说明

步骤1: 添加依赖

步骤2: 创建WebClient实例

步骤3: 构建HTTP请求

步骤4: 处理响应

步骤5: 完整示例代码

常见问题和最佳实践

总结

二、抽象化设计

一、全局WebClient配置

二、通用API Service封装

三、业务Service实现

四、Controller调用示例

五、定时任务调用示例

六、关键设计说明


在Spring Boot项目中,WebClient 是Spring WebFlux模块提供的非阻塞式HTTP客户端,用于高效地调用RESTful API。它支持响应式编程,性能优于传统的RestTemplate。本教程将逐步指导您从零开始集成和使用WebClient,包括依赖配置、实例创建、请求构建、响应处理和完整代码示例。确保您使用Spring Boot 2.x或更高版本(推荐Spring Boot 3.x)。

一、简单说明

步骤1: 添加依赖

首先,在您的Spring Boot项目中添加必要的依赖。WebClient 需要spring-boot-starter-webflux模块,它包含响应式核心库。打开pom.xml文件,添加以下依赖:

<dependencies> <!-- Spring WebFlux for WebClient --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!-- 可选:用于JSON处理,如Jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies> 

如果您使用Gradle,在build.gradle中添加:

dependencies { implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'com.fasterxml.jackson.core:jackson-databind' } 

步骤2: 创建WebClient实例

WebClient 可以通过Spring Bean方式全局配置,或直接在代码中创建。推荐使用Bean方式以便重用和统一配置。

方式2: 直接创建实例 在需要的地方直接构建WebClient

WebClient webClient = WebClient.create("https://api.example.com"); 

方式1: 通过Bean全局配置(推荐) 在Spring配置类中定义WebClient Bean。例如,创建一个WebClientConfig类:

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class WebClientConfig { @Bean public WebClient webClient() { return WebClient.builder() .baseUrl("https://api.example.com") // 设置基础URL,可选 .defaultHeader("Content-Type", "application/json") // 默认请求头 .build(); } } 
步骤3: 构建HTTP请求

WebClient 支持GET、POST、PUT、DELETE等方法。使用链式调用来设置URL、头信息、查询参数和请求体。

POST请求示例:发送JSON数据到第三方API。

import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class ApiClient { public Mono<String> postData(String apiPath, Object requestBody) { return webClient.post() .uri(apiPath) .header("Content-Type", "application/json") .bodyValue(requestBody) // 设置请求体,自动序列化为JSON .retrieve() .bodyToMono(String.class); } } 

GET请求示例:调用一个第三方API获取数据。

import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class ApiClient { private final WebClient webClient; public ApiClient(WebClient webClient) { this.webClient = webClient; } public Mono<String> getData(String apiPath) { return webClient.get() .uri(apiPath) // 例如: "/users" .header("Authorization", "Bearer your_token") // 添加认证头 .retrieve() // 发送请求 .bodyToMono(String.class); // 将响应体解析为String } } 
步骤4: 处理响应

WebClient 返回MonoFlux对象,您需要订阅来处理响应。响应处理包括错误处理和反序列化。

反序列化为对象:如果第三方API返回JSON,使用Jackson自动映射到Java对象。

public class User { private Long id; private String name; // Getters and setters } // 在ApiClient中 public Mono<User> getUserObject(String apiPath) { return webClient.get() .uri(apiPath) .retrieve() .bodyToMono(User.class); // 直接映射到User对象 } 

异步处理(推荐):在Controller中使用响应式风格。

import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @RestController public class UserController { private final ApiClient apiClient; public UserController(ApiClient apiClient) { this.apiClient = apiClient; } @GetMapping("/user") public Mono<String> getUser() { return apiClient.getData("/users/1") .onErrorResume(e -> Mono.just("Error: " + e.getMessage())); // 错误处理 } } 

基本响应处理:使用block()同步获取结果(不推荐在生产中用,测试可用),或异步处理。

// 在Service类中调用 public class UserService { private final ApiClient apiClient; public UserService(ApiClient apiClient) { this.apiClient = apiClient; } public String fetchUserData() { Mono<String> response = apiClient.getData("/users/1"); return response.block(); // 同步获取,仅用于演示 } } 
步骤5: 完整示例代码

以下是一个完整的Spring Boot应用示例,包括配置、服务和控制器。

主应用 (SpringBootApplication.java):

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } 

控制器 (UserController.java):

import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @RestController public class UserController { private final ApiClient apiClient; public UserController(ApiClient apiClient) { this.apiClient = apiClient; } @GetMapping("/posts") public Mono<String> getPosts() { return apiClient.getPosts(); } } 

API客户端 (ApiClient.java):

import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; @Component public class ApiClient { private final WebClient webClient; public ApiClient(WebClient webClient) { this.webClient = webClient; } public Mono<String> getPosts() { return webClient.get() .uri("/posts") .retrieve() .bodyToMono(String.class); } } 

配置类 (WebClientConfig.java):

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class WebClientConfig { @Bean public WebClient webClient() { return WebClient.builder() .baseUrl("https://jsonplaceholder.typicode.com") // 免费测试API .build(); } } 
常见问题和最佳实践
  • 性能优化WebClient是非阻塞的,适合高并发场景。确保整个调用链使用响应式编程(如返回Mono/Flux)。
  • 测试:使用WebTestClient进行单元测试,模拟第三方API。

超时配置:设置请求超时,避免阻塞。

WebClient.builder() .clientConnector(new ReactorClientHttpConnector( HttpClient.create().responseTimeout(Duration.ofSeconds(10)) )) .build(); 

错误处理:使用onErrorResumeonStatus处理HTTP错误(例如404或500)。

return webClient.get() .uri("/invalid-path") .retrieve() .onStatus(status -> status.is4xxClientError(), response -> Mono.error(new RuntimeException("Client error"))) .bodyToMono(String.class); 
总结

通过本教程,您学会了在Spring Boot中使用WebClient调用第三方接口:

  1. 添加spring-boot-starter-webflux依赖。
  2. 配置WebClient Bean。
  3. 构建GET/POST请求并处理响应。
  4. 使用异步处理和错误机制。
  5. 完整代码示例可直接运行。

WebClient 的优势包括高吞吐量、低资源消耗和现代化API设计。如果您遇到问题,请参考Spring官方文档。在实际项目中,确保添加日志和监控以跟踪请求。

二、抽象化设计

以下是根据需求设计的Spring Boot项目结构,包含通用API Service封装、业务Service及调用示例:

一、全局WebClient配置

@Configuration public class WebClientConfig { @Bean public WebClient webClient() { return WebClient.builder() .filter(logRequest()) // 请求日志过滤器 .filter(logResponse()) // 响应日志过滤器 .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .build(); } private ExchangeFilterFunction logRequest() { return (request, next) -> { log.info("Request: {} {}", request.method(), request.url()); request.headers().forEach((name, values) -> values.forEach(value -> log.info("Header: {}={}", name, value))); return next.exchange(request); }; } private ExchangeFilterFunction logResponse() { return ExchangeFilterFunction.ofResponseProcessor(response -> { log.info("Response status: {}", response.statusCode()); return Mono.just(response); }); } } 

二、通用API Service封装

@Service @Slf4j public class ApiService { private final WebClient webClient; public ApiService(WebClient webClient) { this.webClient = webClient; } // 同步调用 public <T, R> R callSync(String url, HttpMethod method, @Nullable T requestBody, Class<R> responseType, MultiValueMap<String, String> headers) { log.info("Request body: {}", toJson(requestBody)); try { WebClient.RequestBodySpec requestSpec = webClient.method(method) .uri(url) .headers(h -> h.addAll(headers)); if (requestBody != null) { requestSpec.bodyValue(requestBody); } return requestSpec.retrieve() .onStatus(HttpStatusCode::isError, this::handleError) .bodyToMono(responseType) .doOnNext(res -> log.info("Response body: {}", toJson(res))) .block(); } catch (WebClientResponseException e) { log.error("API call failed: status={}, body={}", e.getStatusCode(), e.getResponseBodyAsString()); throw new ApiException("API调用失败", e); } catch (Exception e) { log.error("Unexpected error", e); throw new ApiException("系统异常", e); } } // 异步调用 public <T, R> Mono<R> callAsync(String url, HttpMethod method, @Nullable T requestBody, Class<R> responseType, MultiValueMap<String, String> headers) { log.info("Async request body: {}", toJson(requestBody)); WebClient.RequestBodySpec requestSpec = webClient.method(method) .uri(url) .headers(h -> h.addAll(headers)); if (requestBody != null) { requestSpec.bodyValue(requestBody); } return requestSpec.retrieve() .onStatus(HttpStatusCode::isError, this::handleError) .bodyToMono(responseType) .doOnNext(res -> log.info("Async response body: {}", toJson(res))) .onErrorResume(WebClientResponseException.class, ex -> { log.error("Async API error: status={}, body={}", ex.getStatusCode(), ex.getResponseBodyAsString()); return Mono.error(new ApiException("异步调用失败", ex)); }); } private Mono<Throwable> handleError(ClientResponse response) { return response.bodyToMono(String.class) .flatMap(body -> { log.error("Error response: status={}, body={}", response.statusCode(), body); return Mono.error(new WebClientResponseException( response.statusCode().value(), "API Error", response.headers().asHttpHeaders(), body.getBytes(), StandardCharsets.UTF_8 )); }); } private String toJson(Object obj) { try { return new ObjectMapper().writeValueAsString(obj); } catch (JsonProcessingException e) { log.warn("JSON serialization error", e); return "{}"; } } } // 自定义异常 public class ApiException extends RuntimeException { public ApiException(String message, Throwable cause) { super(message, cause); } } 

三、业务Service实现

@Service @Slf4j public class BusinessService { private final ApiService apiService; // 业务请求体封装 @Data @AllArgsConstructor @NoArgsConstructor public static class BusinessRequest { private String orderId; private Integer amount; } // 业务响应体封装 @Data public static class BusinessResponse { private String transactionId; private LocalDateTime processTime; } public BusinessResponse executeBusinessLogic(String param) { // 1. 构建请求参数 BusinessRequest request = new BusinessRequest(param, 100); HttpHeaders headers = new HttpHeaders(); headers.add("X-Client-ID", "business-service"); // 2. 调用API return apiService.callSync( "https://api.thirdparty.com/endpoint", HttpMethod.POST, request, BusinessResponse.class, headers ); } public Mono<BusinessResponse> executeAsyncBusiness(String param) { BusinessRequest request = new BusinessRequest(param, 200); HttpHeaders headers = new HttpHeaders(); headers.add("X-Async", "true"); return apiService.callAsync( "https://api.thirdparty.com/async", HttpMethod.POST, request, BusinessResponse.class, headers ); } } 

四、Controller调用示例

@RestController @RequestMapping("/api") @RequiredArgsConstructor public class BusinessController { private final BusinessService businessService; @PostMapping("/process") public ResponseEntity<BusinessService.BusinessResponse> processOrder(@RequestParam String orderId) { return ResponseEntity.ok(businessService.executeBusinessLogic(orderId)); } } 

五、定时任务调用示例

@Component @Slf4j @RequiredArgsConstructor public class ScheduledTask { private final BusinessService businessService; @Scheduled(fixedRate = 30000) public void runBatchJob() { businessService.executeAsyncBusiness("BATCH_001") .subscribe( response -> log.info("Batch processed: {}", response.getTransactionId()), error -> log.error("Batch failed", error) ); } } 

六、关键设计说明

  1. 日志记录
    • 使用SLF4J的@Slf4j注解
    • 记录原始请求/响应JSON(通过Jackson序列化)
    • 异常场景单独记录错误日志
  2. 异常处理
    • 自定义ApiException统一封装异常
    • 区分HTTP错误状态码(4xx/5xx)
    • 处理网络超时等底层异常
  3. 类型安全
    • 请求/响应使用泛型参数化
    • 业务层DTO对象封装数据
    • 支持任意复杂对象自动序列化
  4. 全局配置
    • WebClient统一配置超时/编码/拦截器
    • 通过过滤器实现全局日志
    • 默认JSON内容类型
  5. 调用方式
    • 同步调用:直接返回结果对象
    • 异步调用:返回Mono<T>响应式流
    • 支持GET/POST等HTTP方法
使用示例:业务Service只需关注自身DTO定义,调用时传入URL、方法类型、请求对象和响应类型即可完成三方接口调用,日志和异常处理由底层自动完成。

Read more

OpenClaw 实操指南 07:飞书 CLI 开源:让 AI 真正接管你的飞书全流程

OpenClaw 实操指南 07:飞书 CLI 开源:让 AI 真正接管你的飞书全流程

2026年3月28日,飞书官方开源larksuite/cli(v1.0.0),以200+命令、19个AI Agent Skills,将飞书2500+开放API封装为命令行接口,面向人类开发者与AI Agent双用户,重构办公协作的操作范式。这不仅是工具升级,更是飞书从“GUI服务人”到“GUI+CLI双态并行”的战略跃迁——GUI给人交互,CLI给AI执行,让AI真正成为办公的“执行者”而非“旁观者”。 一、飞书CLI是什么:从API到命令行的能力跃迁 1. 核心定位与架构 飞书CLI是官方开源、MIT协议、免费商用的命令行工具,核心定位是让AI Agent直接操控飞书全量数据与业务,而非仅做信息查询。其三层架构清晰划分能力边界: * Shortcuts层:高频快捷命令(如lark-cli calendar +agenda查今日日程),降低人类使用门槛。 * API Commands层:200+

高效集成Gemini API:Zotero学术场景AI辅助分析全指南

高效集成Gemini API:Zotero学术场景AI辅助分析全指南 【免费下载链接】zotero-gptGPT Meet Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-gpt 如何在Zotero中用Gemini提升文献管理效率? 在文献管理与AI辅助分析深度融合的今天,Zotero-GPT插件集成Gemini API为学术研究者带来了全新可能。作为一款强大的学术效率工具,这一集成能够帮助研究者在文献筛选、内容摘要、跨语言分析等场景中显著提升工作效率。本文将通过"场景-问题-方案"框架,详细介绍如何在实际研究中高效配置和应用Gemini API,解决常见技术难题,实现AI赋能的文献管理新体验。 学术场景应用案例:Gemini如何助力研究工作流? 场景一:跨语言文献快速综述——如何突破语言壁垒高效整合国际研究? 某环境科学研究者需要整合中英文文献进行气候变化综述。传统方法需手动翻译摘要、提取关键发现,耗时且易遗漏重要信息。通过Zotero-GPT集成的Gemini API,研究者实现了: 1. 一键翻译日

量化、算子融合、内存映射:C语言实现AI推理的“三板斧“

量化、算子融合、内存映射:C语言实现AI推理的“三板斧“

量化、算子融合、内存映射:C语言实现AI推理的"三板斧" 摘要:做嵌入式AI开发的同学,大概率都遇到过这样的困境:训练好的AI模型(比如CNN),在PC上用TensorFlow/PyTorch跑起来流畅丝滑,可移植到单片机、MCU等边缘设备上,要么内存爆掉,要么推理延迟高到无法使用——毕竟边缘设备的资源太有限了:几百KB的RAM、几MB的Flash、没有GPU加速,甚至连浮点运算都要靠软件模拟。这时,依赖庞大的深度学习框架就成了“杀鸡用牛刀”,甚至根本无法运行。而C语言,作为嵌入式开发的“母语”,凭借其极致的性能控制、内存可控性和无 runtime 依赖的优势,成为边缘设备AI推理引擎的最佳选择。但纯C语言实现AI推理,绝不是简单地“用C重写框架代码”,关键在于掌握三大核心优化技术——这就是我们今天要讲的AI推理“三板斧”:量化、算子融合、内存映射。 它们三者协同作用,能从“体积、速度、内存”三个维度彻底优化AI推理性能:

新手必看!用Python手把手教你写第一个AI小工具

新手必看!用Python手把手教你写第一个AI小工具

欢迎文末添加好友交流,共同进步! “ 俺はモンキー・D・ルフィ。海贼王になる男だ!” * 📖 写在前面 * 🎯 项目简介:智能PDF文档助手 * 功能特性 * 项目亮点 * 🛠️ 环境准备 * 2.1 Python环境检查 * 2.2 安装依赖库 * 2.3 获取OpenAI API Key * 📝 项目结构设计 * 💻 核心代码实现 * 3.1 配置文件 (config.py) * 3.2 PDF读取模块 (pdf_reader.py) * 3.3 AI客户端模块 (ai_client.py) * 3.4 主程序入口 (main.py) * 📊 项目功能流程图 * 🎯 使用示例 * 4.