跳到主要内容
Spring Boot 项目使用 WebClient 调用第三方接口详细教程 | 极客日志
Java java
Spring Boot 项目使用 WebClient 调用第三方接口详细教程 综述由AI生成 在 Spring Boot 项目中集成和使用 WebClient 的详细教程。内容涵盖依赖配置、实例创建(Bean 方式与直接创建)、HTTP 请求构建(GET/POST)、响应处理(反序列化与异步)、完整代码示例以及最佳实践。此外,还展示了抽象化设计方案,包括全局配置、通用 API Service 封装、业务 Service 实现及 Controller 和定时任务调用示例,旨在提供高并发场景下的高效 RESTful API 调用方案。
云间运维 发布于 2026/4/5 更新于 2026/5/17 23 浏览一、简单说明
步骤 1: 添加依赖
首先,在您的 Spring Boot 项目中添加必要的依赖。WebClient 需要 spring-boot-starter-webflux 模块,它包含响应式核心库。打开 pom.xml 文件,添加以下依赖:
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-webflux</artifactId >
</dependency >
<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 方式以便重用和统一配置。
方式 1: 通过 Bean 全局配置(推荐) 在 Spring 配置类中定义 WebClient Bean。例如,创建一个 WebClientConfig 类:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
org.springframework.web.reactive.function.client.WebClient;
{
WebClient {
WebClient.builder()
.baseUrl( )
.defaultHeader( , )
.build();
}
}
import
@Configuration
public
class
WebClientConfig
@Bean
public
webClient
()
return
"https://api.example.com"
"Content-Type"
"application/json"
方式 2: 直接创建实例 在需要的地方直接构建 WebClient:
WebClient webClient = WebClient.create("https://api.example.com" );
步骤 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 {
private final WebClient webClient;
public ApiClient (WebClient webClient) {
this .webClient = webClient;
}
public Mono<String> postData (String apiPath, Object requestBody) {
return webClient.post()
.uri(apiPath)
.header("Content-Type" , "application/json" )
.bodyValue(requestBody)
.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)
.header("Authorization" , "Bearer your_token" )
.retrieve()
.bodyToMono(String.class);
}
}
步骤 4: 处理响应 WebClient 返回 Mono 或 Flux 对象,您需要订阅来处理响应。响应处理包括错误处理和反序列化。
反序列化为对象 :如果第三方 API 返回 JSON,使用 Jackson 自动映射到 Java 对象。
public class User {
private Long id;
private String name;
}
public Mono<User> getUserObject (String apiPath) {
return webClient.get()
.uri(apiPath)
.retrieve()
.bodyToMono(User.class);
}
异步处理(推荐) :在 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() 同步获取结果(不推荐在生产中用,测试可用),或异步处理。
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 应用示例,包括配置、服务和控制器。
主应用 (DemoApplication.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" )
.build();
}
}
常见问题和最佳实践
性能优化 :WebClient 是非阻塞的,适合高并发场景。确保整个调用链使用响应式编程(如返回 Mono/Flux)。
测试 :使用 WebTestClient 进行单元测试,模拟第三方 API。
WebClient.builder()
.clientConnector(new ReactorClientHttpConnector (
HttpClient.create().responseTimeout(Duration.ofSeconds(10 ))
))
.build();
错误处理 :使用 onErrorResume 或 onStatus 处理 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 调用第三方接口:
添加 spring-boot-starter-webflux 依赖。
配置 WebClient Bean。
构建 GET/POST 请求并处理响应。
使用异步处理和错误机制。
完整代码示例可直接运行。
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) {
BusinessRequest request = new BusinessRequest (param, 100 );
HttpHeaders headers = new HttpHeaders ();
headers.add("X-Client-ID" , "business-service" );
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)
);
}
}
六、关键设计说明
日志记录
使用 SLF4J 的 @Slf4j 注解
记录原始请求/响应 JSON(通过 Jackson 序列化)
异常场景单独记录错误日志
异常处理
自定义 ApiException 统一封装异常
区分 HTTP 错误状态码(4xx/5xx)
处理网络超时等底层异常
类型安全
请求/响应使用泛型参数化
业务层 DTO 对象封装数据
支持任意复杂对象自动序列化
全局配置
WebClient 统一配置超时/编码/拦截器
通过过滤器实现全局日志
默认 JSON 内容类型
调用方式
同步调用:直接返回结果对象
异步调用:返回 Mono<T> 响应式流
支持 GET/POST 等 HTTP 方法
使用示例:业务 Service 只需关注自身 DTO 定义,调用时传入 URL、方法类型、请求对象和响应类型即可完成三方接口调用,日志和异常处理由底层自动完成。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online