• Spring WebClient 基于响应式编程模型的HTTP客户端


    图片

    一、简介

    WebClient是一个非阻塞的、可扩展的、基于Reactive Streams规范的HTTP客户端。它提供了一种简洁的方式来进行HTTP请求,并且可以很好地与其他Spring组件集成。WebClient支持同步和异步操作,使得它非常适合用于构建响应式应用程序。

    WebClient允许开发者通过构建链式的HTTP请求和响应处理函数来构建异步和非阻塞式的HTTP客户端。它支持多种HTTP方法、请求和响应处理、错误处理、HTTP认证和与RESTful服务交互。

    二、特性

    非阻塞:WebClient使用非阻塞I/O模型,这意味着它可以在等待服务器响应时执行其他任务,从而提高应用程序的性能。

    可扩展性:WebClient可以轻松地与其他Spring组件集成,如Spring MVC、Spring Data REST等。此外,它还支持自定义拦截器和转换器,以满足特定的需求。

    支持反应式编程:WebClient完全符合Reactive Streams规范,因此可以很好地与响应式编程框架(如RxJava、Reactor等)一起使用。

    简化HTTP请求:WebClient提供了简洁的API,使得发送HTTP请求变得更加容易。例如,你可以使用webClient.get()方法来发送一个GET请求,或者使用webClient.postForEntity()方法来发送一个POST请求并接收一个实体对象。

    三、WebClient与RestTemplate区别

    RestTemplate是Spring提供的一个基于模板化的HTTP客户端,它已经过时,不再建议使用。以下是WebClient与RestTemplate的一些主要区别:

    1. 非阻塞:RestTemplate是非阻塞的,而WebClient默认情况下是阻塞的。但是,你可以通过设置client.configurator().setConnectTimeout(Duration.ofSeconds(10))来让WebClient在连接超时时抛出异常。

    2. 可扩展性:WebClient更容易与其他Spring组件集成,因为它是一个更高级别的抽象。而RestTemplate需要手动创建HttpComponentsClientHttpRequestFactory实例,这可能会比较复杂。

    3. 支持反应式编程:WebClient完全符合Reactive Streams规范,因此可以很好地与响应式编程框架一起使用。而RestTemplate不支持反应式编程。

    4. 错误处理:RestTemplate的错误处理是通过回调函数进行的,这使得错误处理变得复杂。而WebClient的错误处理更加直观,因为它支持直接使用try-catch语句捕获异常。

    5. 配置选项:RestTemplate的配置选项较少,而WebClient提供了更多的配置选项,如连接超时、重试策略等。

    四、Spring Boot集成WebClient

    在Spring Boot中集成WebClient非常简单,只需添加以下依赖即可:

    1. org.springframework.boot
    2. spring-boot-starter-webflux

    接下来,我们创建一个WebClient实例,并演示如何发送同步和异步请求:

    1. import org.springframework.web.reactive.function.client.WebClient;
    2. import reactor.core.publisher.Mono;
    3. import reactor.core.scheduler.Schedulers;
    4. public class WebClientExample {
    5. public static void main(String[] args) {
    6. // 创建一个WebClient实例
    7. WebClient webClient = WebClient.create("https://api.example.com");
    8. // 发送一个GET请求并接收一个Mono对象(同步请求)
    9. Mono response = webClient.get()
    10. .uri("/resource")
    11. .retrieve()
    12. .bodyToMono(String.class);
    13. response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    14. // 发送一个POST请求并接收一个Mono对象(异步请求)
    15. Mono asyncResponse = webClient.post()
    16. .uri("/resource")
    17. .bodyValue("Hello, World!") // 设置请求体内容
    18. .retrieve() // 返回响应体而不是完整的响应对象
    19. .bodyToMono(String.class); // 将响应体转换为Mono对象
    20. asyncResponse.subscribeOn(Schedulers.boundedElastic()) // 指定异步执行的任务线程池
    21. .subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    22. }
    23. }

    在这个示例中,我们首先创建了一个WebClient实例,然后使用get()方法发送一个GET请求并接收一个Mono对象。我们使用uri()方法指定请求的URI,然后调用retrieve()方法来获取响应体。最后,我们使用bodyToMono()方法将响应体转换为一个Mono对象,并订阅它以打印结果。

    五、网络客户端

    Spring WebClient是一个基于Reactive Streams规范的非阻塞式HTTP客户端,它提供了创建网络客户端的功能。下面是使用Spring WebClient创建网络客户端的示例代码:

    1. import org.springframework.web.reactive.function.client.WebClient;
    2. public class WebClientExample {
    3. public static void main(String[] args) {
    4. // 创建一个WebClient实例
    5. WebClient webClient = WebClient.create("https://api.example.com");
    6. // 发送一个GET请求并接收一个Mono对象
    7. Mono response = webClient.get()
    8. .uri("/resource")
    9. .retrieve()
    10. .bodyToMono(String.class);
    11. // 订阅响应并打印结果
    12. response.subscribe(System.out::println);
    13. }
    14. }

    在这个示例中,我们首先创建了一个WebClient实例,然后使用get()方法发送一个GET请求并接收一个Mono对象。我们使用uri()方法指定请求的URI,然后调用retrieve()方法来获取响应体。最后,我们使用bodyToMono()方法将响应体转换为一个Mono对象,并订阅它以打印结果。

    除了发送GET请求外,我们还可以使用其他方法来发送不同类型的请求,例如POST、PUT和DELETE等。例如,我们可以使用post()方法发送一个POST请求:

    1. import org.springframework.web.reactive.function.client.WebClient;
    2. public class WebClientExample {
    3. public static void main(String[] args) {
    4. // 创建一个WebClient实例
    5. WebClient webClient = WebClient.create("https://api.example.com");
    6. // 发送一个POST请求并接收一个Mono对象
    7. Mono response = webClient.post()
    8. .uri("/resource")
    9. .bodyValue("Hello, World!") // 设置请求体内容
    10. .retrieve() // 返回响应体而不是完整的响应对象
    11. .bodyToMono(String.class); // 将响应体转换为Mono对象
    12. // 订阅响应并打印结果
    13. response.subscribe(System.out::println);
    14. }
    15. }

    在这个示例中,我们使用post()方法发送一个POST请求,并使用bodyValue()方法设置请求体内容。我们同样使用retrieve()方法来获取响应体,并使用bodyToMono()方法将响应体转换为一个Mono对象。最后,我们订阅这个Mono对象以打印响应结果。

    六、错误处理机制

    Spring WebClient提供了多种错误处理机制,包括异常处理、重试策略和自定义错误处理。下面将分别介绍这些错误处理方式,并给出相应的代码示例。

    6.1 异常处理

    WebClient支持使用onErrorResume方法来处理请求过程中发生的异常。例如:

    1. import org.springframework.web.reactive.function.client.WebClient;
    2. import reactor.core.publisher.Mono;
    3. public class WebClientExample {
    4. public static void main(String[] args) {
    5. // 创建一个WebClient实例
    6. WebClient webClient = WebClient.create("https://api.example.com");
    7. // 发送一个GET请求并处理异常
    8. Mono response = webClient.get()
    9. .uri("/resource")
    10. .retrieve()
    11. .onErrorResume(e -> {
    12. // 打印异常信息
    13. System.err.println("Request failed: " + e.getMessage());
    14. // 返回一个空的Mono对象,表示请求失败
    15. return Mono.empty();
    16. });
    17. response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    18. }
    19. }

    在这个示例中,我们使用onErrorResume方法来处理请求过程中发生的异常。当发生异常时,我们打印异常信息,并返回一个空的Mono对象,表示请求失败。

    6.2 重试策略

    WebClient支持多种重试策略,如固定延迟重试、指数退避重试等。以下是使用固定延迟重试的示例:

    1. import org.springframework.http.client.reactive.ReactorClientHttpConnector;
    2. import org.springframework.web.reactive.function.client.WebClient;
    3. import reactor.core.publisher.Mono;
    4. public class WebClientRetryExample {
    5. public static void main(String[] args) {
    6. // 创建一个WebClient实例
    7. WebClient webClient = WebClient.builder()
    8. .baseUrl("https://api.example.com")
    9. .clientConnector(new ReactorClientHttpConnector())
    10. .build();
    11. // 发送一个GET请求并设置重试策略
    12. Mono response = webClient.get()
    13. .uri("/resource")
    14. .retrieve()
    15. .bodyToMono(String.class)
    16. .retryWhen(e -> e instanceof java.net.SocketTimeoutException || e instanceof java.net.UnknownHostException) // 当发生SocketTimeoutException或UnknownHostException时进行重试
    17. .delayElements(Duration.ofSeconds(1)); // 设置重试间隔为1秒
    18. response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    19. }
    20. }

    在这个示例中,我们使用retryWhen方法来设置重试策略。当发生SocketTimeoutException或UnknownHostException时,我们进行重试。同时,我们使用delayElements方法来设置重试间隔。

    6.3 自定义错误处理

    除了使用异常处理和重试策略外,你还可以通过实现ClientResponse接口来自定义错误处理逻辑。例如:

    1. import org.springframework.http.client.ClientHttpResponse;
    2. import org.springframework.web.reactive.function.client.WebClient;
    3. import reactor.core.publisher.Mono;
    4. public class CustomErrorHandlingExample {
    5. public static void main(String[] args) {
    6. // 创建一个WebClient实例
    7. WebClient webClient = WebClient.create("https://api.example.com");
    8. // 发送一个GET请求并自定义错误处理逻辑
    9. Mono response = webClient.get()
    10. .uri("/resource")
    11. .retrieve()
    12. .onStatus(status -> status.is4xxClientError(), clientResponse -> {
    13. // 当发生4xx客户端错误时,返回一个空的Mono对象,表示请求失败
    14. return Mono.empty();
    15. })
    16. .onStatus(status -> status.is5xxServerError(), clientResponse -> {
    17. // 当发生5xx服务器错误时,返回一个空的Mono对象,表示请求失败
    18. return Mono.empty();
    19. });
    20. response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    21. }
    22. }

    在这个示例中,我们使用onStatus方法来自定义错误处理逻辑。当发生4xx客户端错误或5xx服务器错误时,我们返回一个空的Mono对象,表示请求失败。

    七、结语

    在 Spring Framework 5.0 及更高版本中,RestTemplate 已被弃用,取而代之的是较新的 WebClient。由于 RestTemplace 已弃用,开发人员应开始使用 WebClient 进行 REST 调用,非阻塞 I/O 调用会提高应用程序性能。

    图片

  • 相关阅读:
    从三个层面分析如何创造高价值专利?
    Yakit工具篇:爆破与未授权检测的使用
    Linux openGauss 数据库远程连接
    UGUI不规则响应区域(例如多个按钮重叠,避免点击错误)
    某60区块链安全之Call函数簇滥用实战一学习记录
    CSS 6 CSS 盒子模型
    react库的基础学习
    Flume启停脚本f1.sh
    【C++】vector的模拟实现【完整版】
    STM32 | 独立看门狗 | RTC(实时时钟)
  • 原文地址:https://blog.csdn.net/weixin_40381772/article/details/133737276