掌握 Spring 中的 WebClient

简介: 本文介绍了 Spring Boot 开发中 WebClient 的使用场景及优势。WebClient 是非阻塞响应式 Web 客户端,适合高并发、流式数据处理和微服务通信。它支持事件驱动架构、大文件传输、超时重试机制,并可与 OAuth2 集成实现安全通信。相比 RestTemplate,WebClient 提供更高效的资源利用和灵活的并发处理能力,适用于现代响应式应用开发。文中通过代码示例详细对比了两者的区别,展示了 WebClient 在异步编程中的强大功能。

在开发 Spring Boot 应用程序时经常需要与其他 Web 服务进行通信。过去,开发人员通常使用 RestTemplate 来实现这一目的。然而,随着响应式编程的出现以及对更高效资源利用的需求,WebClient 已成为更优选择。

WebClient 是 Spring WebFlux 框架引入的非阻塞响应式 Web 客户端。它旨在支持异步和流式场景,非常适合需要高并发和可扩展性的应用程序。

响应式应用

在开发响应式应用程序时,WebClient 是首选。响应式编程旨在通过利用非阻塞 I/O 高效处理大量并发请求。在以下情况下优先使用 WebClient:

  • 响应式 API:如果您的应用程序使用 Reactor、RxJava 或其他响应式框架,WebClient 可以无缝集成。
  • 事件驱动架构:依赖事件的系统,如物联网平台。

示例:

java

体验AI代码助手

代码解读

复制代码

public Mono<User> fetchUser(String userId) {
    return WebClient.create()
           .get()
           .uri("https://api.example.com/users/{id}", userId)
           .retrieve()
           .bodyToMono(User.class);
}

微服务通信

在微服务架构中,服务之间经常需要相互通信。WebClient 实现高效、高吞吐量的服务间通信。它允许:

  • 并发请求:同时发送多个请求而不阻塞线程。
  • 低延迟:以更短的响应时间处理实时数据。

示例:

java

体验AI代码助手

代码解读

复制代码

public Flux<Order> fetchUserOrders(String userId) {
    return WebClient.create()
           .get()
           .uri("https://orderservice.com/orders?userId=" + userId)
           .retrieve()
           .bodyToFlux(Order.class);
}

流式和实时数据

WebClient 在处理流式数据和服务器发送事件(SSE)方面表现出色。对于需要以下功能的应用程序使用 WebClient:

  • 数据流:例如,消费实时股票价格更新或传感器数据。
  • 长连接:处理 WebSockets 或 SSE,如聊天或实时仪表板应用。

示例:

java

体验AI代码助手

代码解读

复制代码

public Flux<StockPrice> streamStockPrices() {
    return WebClient.create()
           .get()
           .uri("https://api.example.com/stock-prices/stream")
           .retrieve()
           .bodyToFlux(StockPrice.class);
}

处理大负载

处理大文件上传/下载或流式传输大数据集的应用程序应使用 WebClient,因为它能高效利用资源:

  • 由于其非阻塞 I/O,可实现高效内存处理。
  • 支持流式传输数据块,而无需将整个内容加载到内存中。

示例:

java

体验AI代码助手

代码解读

复制代码

public Flux<DataChunk> downloadLargeFile() {
    return WebClient.create()
           .get()
           .uri("https://api.example.com/largefile")
           .retrieve()
           .bodyToFlux(DataChunk.class);
}

重试、熔断、超时

WebClient 与 Resilience4j 等库集成,提供自动失败重试、熔断、超时控制的能力:

示例:

java

体验AI代码助手

代码解读

复制代码

import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import reactor.core.publisher.Mono;

CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("myService");

public Mono<User> fetchUserWithResilience(String userId) {
    return WebClient.create()
           .get()
           .uri("https://api.example.com/users/{id}", userId)
           .retrieve()
           .bodyToMono(User.class)
           .transformDeferred(CircuitBreakerOperator.of(circuitBreaker));
}

身份认证

WebClient 也提供支持安全的通信方式:

  • OAuth2 集成:与 Spring Security 配合使用,处理 OAuth2 令牌管理。
  • 自定义身份验证:配置自定义标头或令牌以进行安全通信。

示例:

java

体验AI代码助手

代码解读

复制代码

public Mono<User> fetchUserWithToken(String userId, String token) {
    return WebClient.builder()
           .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token)
           .build()
           .get()
           .uri("https://api.example.com/users/{id}", userId)
           .retrieve()
           .bodyToMono(User.class);
}

MOCK API

WebClient 适合用于测试,因为它与 WireMock 等模拟服务器集成:

  • 模拟 API 响应以进行集成测试。
  • 测试超时或错误代码等失败场景。

示例:

java

体验AI代码助手

代码解读

复制代码

import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;

importstatic com.github.tomakehurst.wiremock.client.WireMock.*;
importstatic org.junit.jupiter.api.Assertions.*;

publicclass WebClientTest {

    @Test
    public void testFetchUser() {
        WireMockServer wireMockServer = new WireMockServer();
        wireMockServer.start();

        wireMockServer.stubFor(get(urlEqualTo("/users/1"))
               .willReturn(aResponse()
                       .withHeader("Content-Type", "application/json")
                       .withBody("{\"id\":1,\"name\":\"John Doe\"}")));

        WebClient webClient = WebClient.create(wireMockServer.baseUrl());
        Mono<User> user =
                webClient.get().uri("/users/1").retrieve().bodyToMono(User.class);

        StepVerifier.create(user)
               .expectNextMatches(u -> u.getName().equals("John Doe"))
               .verifyComplete();

        wireMockServer.stop();
    }
}

WebClient 与 RestTemplate 的对比

WebClient 的优势

  • 非阻塞 I/O:WebClient 使用非阻塞模型,这意味着在等待响应时线程不会被阻塞。当同时进行多个 API 调用时,这一点特别有用。
  • 支持响应式流:WebClient 与 Reactor 和 RxJava 等响应式库无缝集成,适用于现代响应式架构。
  • 更好的可扩展性:非阻塞行为允许 WebClient 同时处理更多请求,而不会耗尽服务器线程。
  • 更强大:WebClient 更灵活且功能丰富,支持高级用例,如流式传输大文件、处理 WebSocket 连接。

调用接口

使用 RestTemplate:

java

体验AI代码助手

代码解读

复制代码

import org.springframework.web.client.RestTemplate;

public class RestTemplateExample {

    private RestTemplate restTemplate = new RestTemplate();

    public String getUserDetails(String userId) {
        String url = "https://api.example.com/users/" + userId;
        return restTemplate.getForObject(url, String.class);
    }
}

使用 WebClient:

java

体验AI代码助手

代码解读

复制代码

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

publicclass WebClientExample {

    private WebClient webClient = WebClient.create();

    public Mono<String> getUserDetails(String userId) {
        String url = "https://api.example.com/users/" + userId;
        return webClient.get()
               .uri(url)
               .retrieve()
               .bodyToMono(String.class);
    }
}

区别:

  • RestTemplate 会阻塞,直到 API 调用完成。
  • WebClient 返回一个 Mono,允许应用程序在等待响应时处理其他任务。

并发调用

使用 RestTemplate:

java

体验AI代码助手

代码解读

复制代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

publicclass RestTemplateConcurrentExample {

    private RestTemplate restTemplate = new RestTemplate();

    public void fetchMultipleUsers(String[] userIds) {
        ExecutorService executor = Executors.newFixedThreadPool(userIds.length);
        for (String userId : userIds) {
            executor.submit(() -> {
                String url = "https://api.example.com/users/" + userId;
                String response = restTemplate.getForObject(url, String.class);
                System.out.println(response);
            });
        }
        executor.shutdown();
    }
}

使用 WebClient:

java

体验AI代码助手

代码解读

复制代码

import reactor.core.publisher.Flux;

public class WebClientConcurrentExample {

    private WebClient webClient = WebClient.create();

    public Flux<String> fetchMultipleUsers(String[] userIds) {
        return Flux.fromArray(userIds)
               .flatMap(userId -> webClient.get()
                       .uri("https://api.example.com/users/" + userId)
                       .retrieve()
                       .bodyToMono(String.class));
    }
}

区别:

  • RestTemplate 需要显式管理线程,增加了复杂性。
  • WebClient 非常方便地处理并发,减少了样板代码。


转载来源:https://juejin.cn/post/7492545417932210212

相关文章
|
Java API Spring
SpringBoot项目调用HTTP接口5种方式你了解多少?
SpringBoot项目调用HTTP接口5种方式你了解多少?
2639 2
|
XML 编解码 Java
Spring Boot 中的 RestTemplate和Retrofit 插件很好
Spring Boot 中的 RestTemplate和Retrofit 插件很好
526 1
|
开发框架 Java 测试技术
SpringBoot3 响应式网络请求客户端
SpringBoot3 响应式网络请求客户端
|
11月前
|
XML 监控 前端开发
Spring Boot中的WebFlux编程模型
Spring WebFlux 是 Spring Framework 5 引入的响应式编程模型,基于 Reactor 框架,支持非阻塞异步编程,适用于高并发和 I/O 密集型应用。本文介绍 WebFlux 的原理、优势及在 Spring Boot 中的应用,包括添加依赖、编写响应式控制器和服务层实现。WebFlux 提供高性能、快速响应和资源节省等优点,适合现代 Web 应用开发。
1322 15
|
Java 测试技术 API
弃用 RestTemplate,来了解一下官方推荐的 WebClient !
在 Spring Framework 5.0 及更高版本中,RestTemplate 已被弃用,取而代之的是 WebClient。WebClient 提供了非阻塞 I/O、函数式编程风格、更好的错误处理和流式传输支持等优势。本文介绍了如何在 Spring Boot 3 中使用 WebClient 发送同步和异步请求,并处理各种错误。虽然 RestTemplate 仍可用于某些场景,但 WebClient 是现代 Spring 应用程序的更好选择。
弃用 RestTemplate,来了解一下官方推荐的 WebClient !
|
负载均衡 Java API
|
Java UED Spring
Springboot通过SSE实现实时消息返回
通过Spring Boot实现SSE,可以简单高效地将实时消息推送给客户端。虽然SSE有其限制,但对于许多实时消息推送场景而言,它提供了一种简洁而强大的解决方案。在实际开发中,根据具体需求选择合适的技术,可以提高系统的性能和用户体验。希望本文能帮助你深入理解Spring Boot中SSE的实现和应用。
5976 1
|
JavaScript Java Kotlin
深入 Spring Cloud Gateway 过滤器
Spring Cloud Gateway 是新一代微服务网关框架,支持多种过滤器实现。本文详解了 `GlobalFilter`、`GatewayFilter` 和 `AbstractGatewayFilterFactory` 三种过滤器的实现方式及其应用场景,帮助开发者高效利用这些工具进行网关开发。
1704 1
|
JSON Java API
技术笔记:springboot项目使用拦截器实现一个简单的网关请求透传
技术笔记:springboot项目使用拦截器实现一个简单的网关请求透传
556 0
|
存储 安全 Java
深度长文解析SpringWebFlux响应式框架15个核心组件源码
以上是Spring WebFlux 框架核心组件的全部介绍了,希望可以帮助你全面深入的理解 WebFlux的原理,关注【威哥爱编程】,主页里可查看V哥每天更新的原创技术内容,让我们一起成长。
726 3