跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

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

在 Spring Boot 项目中集成和使用 WebClient 的详细教程。内容涵盖依赖配置、实例创建(Bean 方式与直接创建)、HTTP 请求构建(GET/POST)、响应处理(反序列化与异步)、完整代码示例以及最佳实践。此外,还展示了抽象化设计方案,包括全局配置、通用 API Service 封装、业务 Service 实现及 Controller 和定时任务调用示例,旨在提供高并发场景下的高效 RESTful API 调用方案。

云间运维发布于 2026/4/5更新于 2026/7/2242 浏览

一、简单说明

步骤 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 方式以便重用和统一配置。

方式 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();
    }
}

方式 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) // 设置请求体,自动序列化为 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 返回 Mono 或 Flux 对象,您需要订阅来处理响应。响应处理包括错误处理和反序列化。

反序列化为对象:如果第三方 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 应用示例,包括配置、服务和控制器。

主应用 (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") // 免费测试 API
                .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 调用第三方接口:

  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、方法类型、请求对象和响应类型即可完成三方接口调用,日志和异常处理由底层自动完成。

目录

  1. 一、简单说明
  2. 步骤 1: 添加依赖
  3. 步骤 2: 创建 WebClient 实例
  4. 步骤 3: 构建 HTTP 请求
  5. 步骤 4: 处理响应
  6. 步骤 5: 完整示例代码
  7. 常见问题和最佳实践
  8. 总结
  9. 二、抽象化设计
  10. 一、全局 WebClient 配置
  11. 二、通用 API Service 封装
  12. 三、业务 Service 实现
  13. 四、Controller 调用示例
  14. 五、定时任务调用示例
  15. 六、关键设计说明
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Claude Code 安装与使用指南
  • Elasticsearch 核心概念、Kibana 测试与 C++ 客户端封装
  • AI Agent 入门:RAG 知识库与智能体架构解析,对比 Coze Dify OpenClaw
  • 分治算法:快速排序及经典题目解析
  • 突破性能瓶颈:llama.cpp多GPU分布式计算优化实践指南
  • AIGC 已步入落地阶段:2025 年六大技术趋势解析
  • 人工智能发展历程与现状分析
  • 基于 Trae Agent 与 MCP Tools 实现 Gitee 自动化辅助
  • Claude Skills 实战:自动化工具安装与使用指南
  • 前端核心知识点梳理与面试复习
  • Stable Diffusion 2024:技术突破与商业落地的开源实践
  • WebCode 与 Clawdbot 深度对比:架构、生态与选型指南
  • 2024 年大模型 LLM 技术学习路线图与核心岗位分析
  • 归并排序:原理、代码实现与复杂度分析
  • AI 写作工具横评:DeepSeek、Kimi、笔灵等 5 款网文创作神器
  • 全球情报监控平台 World Monitor 开源项目介绍
  • SM2 国密算法原理与 C++跨平台实现
  • Nunchaku FLUX.1 CustomV3:AI 绘画快速上手指南
  • 用 Prompt 进行数据清洗:缺失值与异常值自动标注
  • 基于 ClaudeCode 和 Figma-MCP 的 UI 设计 1:1 前端还原方案

相关免费在线工具

  • 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